/// <summary> /// Constructor /// </summary> /// <param name="transform">Transform</param> /// <param name="t">Localized Time</param> /// <param name="interpolationType">Interpolation type to use from this keyframe to the next</param> public gxtKeyframe(gxtAnimationPose pose, float localTime, gxtAnimationInterpolationType interpolationType = gxtAnimationInterpolationType.SMOOTH_STEP) { LocalTime = gxtMath.Saturate(localTime); AnimationPose = pose; InterpolationType = interpolationType; }
/// <summary> /// /// </summary> /// <param name="pose"></param> /// <param name="localTime"></param> /// <param name="interpolationType"></param> /// <returns></returns> public int CreateKeyframe(gxtAnimationPose pose, float localTime, gxtAnimationInterpolationType interpolationType = gxtKeyframe.DEFAULT_INTERPOLATION_TYPE) { gxtKeyframe kf = new gxtKeyframe(pose, localTime, interpolationType); return AddKeyframe(kf); }
/// <summary> /// Performs linear interpolation between two keyframes at the given indices and a value of t /// </summary> /// <param name="tweenT">T</param> /// <param name="keyFrameIndexA">Index A</param> /// <param name="keyFrameIndexB">Index B</param> private void Interpolate(float tweenT, int keyFrameIndexA, int keyFrameIndexB) { poseA = keyframes[keyFrameIndexA].AnimationPose; poseB = keyframes[keyFrameIndexB].AnimationPose; if (keyframes[keyFrameIndexA].InterpolationType == gxtAnimationInterpolationType.SMOOTH_STEP) { // smooth step tmpPosition = gxtMath.SmoothStep(poseA.Translation, poseB.Translation, tweenT); tmpRotation = gxtMath.SmoothStep(poseA.Rotation, poseB.Rotation, tweenT); tmpScale = gxtMath.SmoothStep(poseA.Scale, poseB.Scale, tweenT); if (poseA.InterpolateColorOverlay) { tmpColor = gxtMath.SmoothStep(poseA.ColorOverlay, poseB.ColorOverlay, tweenT); mesh.Material.ColorOverlay = tmpColor; } if (poseA.InterpolateUVCoords) { gxtDebug.SlowAssert(poseA.UVCoordinates != null && poseB.UVCoordinates != null, "Cannot interpolate between null UV Coordinates!"); gxtDebug.SlowAssert(poseA.UVCoordinates.Length == poseB.UVCoordinates.Length, "Cannot interpolate between UV Coordinate arrays of different sizes!"); for (int i = 0; i < poseA.UVCoordinates.Length; ++i) { this.uvCoords[i] = gxtMath.SmoothStep(poseA.UVCoordinates[i], poseB.UVCoordinates[i], tweenT); } mesh.SetTextureCoordinates(uvCoords); } } else if (keyframes[keyFrameIndexA].InterpolationType == gxtAnimationInterpolationType.LERP) { // lerp tmpPosition = gxtMath.Lerp(poseA.Translation, poseB.Translation, tweenT); tmpRotation = gxtMath.Lerp(poseA.Rotation, poseB.Rotation, tweenT); tmpScale = gxtMath.Lerp(poseA.Scale, poseB.Scale, tweenT); if (poseA.InterpolateColorOverlay) { tmpColor = Color.Lerp(poseA.ColorOverlay, poseB.ColorOverlay, tweenT); mesh.Material.ColorOverlay = tmpColor; } if (poseA.InterpolateUVCoords) { gxtDebug.SlowAssert(poseA.UVCoordinates != null && poseB.UVCoordinates != null, "Cannot interpolate between null UV Coordinates!"); gxtDebug.SlowAssert(poseA.UVCoordinates.Length == poseB.UVCoordinates.Length, "Cannot interpolate between UV Coordinate arrays of different sizes!"); for (int i = 0; i < poseA.UVCoordinates.Length; ++i) { this.uvCoords[i] = gxtMath.Lerp(poseA.UVCoordinates[i], poseB.UVCoordinates[i], tweenT); } mesh.SetTextureCoordinates(uvCoords); } } else { // smoother step tmpPosition = gxtMath.SmootherStep(poseA.Translation, poseB.Translation, tweenT); tmpRotation = gxtMath.SmootherStep(poseA.Rotation, poseB.Rotation, tweenT); tmpScale = gxtMath.SmootherStep(poseA.Scale, poseB.Scale, tweenT); if (poseA.InterpolateColorOverlay) { tmpColor = gxtMath.SmootherStep(poseA.ColorOverlay, poseB.ColorOverlay, tweenT); mesh.Material.ColorOverlay = tmpColor; } if (poseA.InterpolateUVCoords) { gxtDebug.SlowAssert(poseA.UVCoordinates != null && poseB.UVCoordinates != null, "Cannot interpolate between null UV Coordinates!"); gxtDebug.SlowAssert(poseA.UVCoordinates.Length == poseB.UVCoordinates.Length, "Cannot interpolate between UV Coordinate arrays of different sizes!"); for (int i = 0; i < poseA.UVCoordinates.Length; ++i) { this.uvCoords[i] = gxtMath.SmootherStep(poseA.UVCoordinates[i], poseB.UVCoordinates[i], tweenT); } mesh.SetTextureCoordinates(uvCoords); } } // set interpolated values node.SetAll(ref tmpPosition, tmpRotation, ref tmpScale); }
/// <summary> /// Shallow copies keep the same collection of UV coords /// This can save a lot of space, especially for big meshes /// But the editor has to handle this optimization carefully /// </summary> /// <param name="state"></param> /// <returns></returns> public static gxtAnimationPose ShallowCopy(gxtAnimationPose animPose) { gxtDebug.Assert(animPose != null); gxtAnimationPose poseCopy = new gxtAnimationPose(); poseCopy.Translation = animPose.Translation; poseCopy.Rotation = animPose.Rotation; poseCopy.Scale = animPose.Scale; poseCopy.ColorOverlay = animPose.ColorOverlay; poseCopy.InterpolateUVCoords = animPose.InterpolateUVCoords; poseCopy.UVCoordinates = animPose.UVCoordinates; poseCopy.InterpolateColorOverlay = animPose.InterpolateColorOverlay; return poseCopy; }
/// <summary> /// /// </summary> /// <param name="animState"></param> /// <param name="numVertices"></param> /// <returns></returns> public static bool IsValid(gxtAnimationPose animPose, int numVertices) { gxtDebug.Assert(numVertices < 3, "A mesh must have at least 3 vertices!"); if (animPose == null) return false; if (animPose.InterpolateUVCoords) if (animPose.UVCoordinates != null) return animPose.UVCoordinates.Length == numVertices; return true; }
/// <summary> /// /// </summary> /// <param name="animState"></param> /// <returns></returns> public static bool IsValid(gxtAnimationPose animPose) { if (animPose == null) return false; if (animPose.InterpolateUVCoords) return animPose.UVCoordinates != null; else return true; }
/// <summary> /// Same as shallow copy, but operates on a newly allocated copy of the UV Coordinates /// </summary> /// <param name="state"></param> /// <returns></returns> public static gxtAnimationPose DeepCopy(gxtAnimationPose animPose) { gxtDebug.Assert(animPose != null); gxtAnimationPose poseCopy = new gxtAnimationPose(); poseCopy.Translation = animPose.Translation; poseCopy.Rotation = animPose.Rotation; poseCopy.Scale = animPose.Scale; poseCopy.ColorOverlay = animPose.ColorOverlay; poseCopy.InterpolateUVCoords = animPose.InterpolateUVCoords; poseCopy.InterpolateColorOverlay = animPose.InterpolateColorOverlay; if (animPose.UVCoordinates != null) { Vector2[] uvCopy = new Vector2[animPose.UVCoordinates.Length]; for (int i = 0; i < uvCopy.Length; ++i) uvCopy[i] = animPose.UVCoordinates[i]; } return poseCopy; }
/// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { base.Initialize(); IsMouseVisible = true; camera = new gxtCamera(Vector2.Zero, 0.0f, 0.0f, false); gxtDisplayManager.Singleton.WindowTitle = "Animation Scene Graph Test"; sceneGraph = new gxtSceneGraph(); sceneGraph.Initialize(); Texture2D grassTexture, metalTexture; bool textureLoaded = gxtResourceManager.Singleton.LoadTexture("Textures\\grass", out grassTexture); gxtDebug.Assert(textureLoaded, "Texture load failed!"); textureLoaded = gxtResourceManager.Singleton.LoadTexture("Textures\\scratched_metal", out metalTexture); gxtDebug.Assert(textureLoaded, "Texture load failed!"); parent = new gxtSceneNode(); Vector2[] rectangleVertices = gxtGeometry.CreateRectangleVertices(150, 100); gxtDynamicMesh rectangle = new gxtDynamicMesh(rectangleVertices); gxtIMaterial rectangleMaterial = new gxtMaterial(true, Color.Yellow, 0.5f); rectangle.Material = rectangleMaterial; rectangle.ApplyTexture(grassTexture, gxtTextureCoordinateType.WRAP); parent.AttachDrawable(rectangle); child = new gxtSceneNode(); child.Position = new Vector2(37.5f, 55.5f); Vector2[] rectangleVertices2 = gxtGeometry.CreateRectangleVertices(75, 175); gxtIMaterial rectangleMaterial2 = new gxtMaterial(true, Color.Blue, 1.0f); gxtDynamicMesh rectangle2 = new gxtDynamicMesh(rectangleVertices2); rectangle2.Material = rectangleMaterial2; rectangle2.ApplyTexture(metalTexture, gxtTextureCoordinateType.WRAP); child.AttachDrawable(rectangle2); parent.AddChild(child); sceneGraph.AddNode(parent); gxtAnimationPose a0 = new gxtAnimationPose(); a0.InterpolateUVCoords = true; a0.InterpolateColorOverlay = true; a0.UVCoordinates = rectangle.GetTextureCoordinates(); gxtAnimationPose a1 = new gxtAnimationPose(); a1.InterpolateUVCoords = false; a1.InterpolateColorOverlay = true; a1.ColorOverlay = Color.Red; a1.Translation = new Vector2(-150, -200); Vector2[] uvCoordsCopy = rectangle.GetTextureCoordinates(); for (int i = 0; i < uvCoordsCopy.Length; ++i) { uvCoordsCopy[i] += new Vector2(-0.75f); } a1.UVCoordinates = uvCoordsCopy; gxtAnimationPose a2 = new gxtAnimationPose(); a2.Translation = new Vector2(200, -225); a2.Rotation = gxtMath.PI_OVER_FOUR; a2.InterpolateUVCoords = false; Vector2[] uvCoordsCopy2 = rectangle.GetTextureCoordinates(); for (int i = 0; i < uvCoordsCopy2.Length; ++i) { uvCoordsCopy2[i] *= (1.0f / 1.5f); //uvCoordsCopy2[i] += new Vector2(-3.75f, 0.0f); } a2.UVCoordinates = uvCoordsCopy2; gxtAnimationPose a3 = new gxtAnimationPose(); a3.Translation = new Vector2(50, 200); a3.Rotation = gxtMath.DegreesToRadians(-235); a3.Scale = new Vector2(1.85f, 1.75f); gxtKeyframe k0 = new gxtKeyframe(a0, 0.0f); gxtKeyframe k1 = new gxtKeyframe(a1, 0.4f); gxtKeyframe k2 = new gxtKeyframe(a2, 0.65f); gxtKeyframe k3 = new gxtKeyframe(a3, 1.0f); gxtAnimationClip clip = new gxtAnimationClip(parent, rectangle); clip.AddKeyframe(k0); clip.AddKeyframe(k1); clip.AddKeyframe(k2); clip.AddKeyframe(k3); animClip = new gxtAnimation(TimeSpan.FromSeconds(5.0), true, true, 1.0f); animClip.AddClip(clip); animController = new gxtAnimationController(); animController.AddAnimation("default", animClip); //animClip.AddTween(); /* gxtAnimationKeyFrame k3 = new gxtAnimationKeyFrame(); */ /* parent = new gxtSceneNode(); //gxtIDrawable rectangleDrawable = new gxtDrawable(Color.Yellow, true, 0.5f); gxtRectangle rectangle = new gxtRectangle(150, 100); gxtIMaterial rectangleMaterial = new gxtMaterial(true, Color.Yellow, 0.2f); rectangle.Material = rectangleMaterial; parent.AttachDrawable(rectangle); child = new gxtSceneNode(); //gxtIDrawable childRectDrawable = new gxtDrawable(Color.Blue, true, 0.0f); gxtRectangle childRect = new gxtRectangle(75, 175); gxtIMaterial childRectangleMaterial = new gxtMaterial(true, new Color(0, 0, 255, 100), 0.0f); childRect.Material = childRectangleMaterial; child.AttachDrawable(childRect); child.Position = new Vector2(37.5f, 55.5f); parent.AddChild(child); sceneGraph.AddNode(parent); initKeyframe = new gxtKeyframe(gxtNodeTransform.Identity, 0.0f); gxtNodeTransform midTransform = new gxtNodeTransform(); midTransform.Translation = new Vector2(-185, -100); midTransform.Scale = new Vector2(-1.5f, 1.5f); midTransform.Rotation = gxtMath.DegreesToRadians(-25.0f); gxtKeyframe midKeyFrame = new gxtKeyframe(midTransform, 0.235f); gxtNodeTransform finalPose = new gxtNodeTransform(); finalPose.Translation = new Vector2(100.0f, -200.0f); finalPose.Rotation = gxtMath.DegreesToRadians(90.0f); finalKeyframe = new gxtKeyframe(finalPose, 0.6f); gxtNodeTransform lastXform = new gxtNodeTransform(); lastXform.Translation = new Vector2(100.0f, -200.0f); lastXform.Rotation = -6.0f * gxtMath.PI; lastXform.Scale = new Vector2(0.25f, 1.45f); gxtKeyframe lastKeyframe = new gxtKeyframe(lastXform, 0.85f); gxtTween tween = new gxtTween(parent); tween.AddKeyframe(initKeyframe); tween.AddKeyframe(finalKeyframe); tween.AddKeyframe(midKeyFrame); tween.AddKeyframe(lastKeyframe); animClip = new gxtAnimationClip(TimeSpan.FromSeconds(10.0)); animClip.AddTween(tween); animClip.Loop = false; animClip.PlaybackRate = 1.0f; animController = new gxtAnimationController(); animController.AddClip("default", animClip); animController.Stop("default"); */ gxtLog.WriteLineV(gxtVerbosityLevel.INFORMATIONAL, "Window Width: {0}", gxtDisplayManager.Singleton.ResolutionWidth); gxtLog.WriteLineV(gxtVerbosityLevel.INFORMATIONAL, "Window Height: {0}", gxtDisplayManager.Singleton.ResolutionHeight); //gxtSprite sprite = new gxtSprite(texture); //sprite.Depth = 0.0f; //sprite.Alpha = 100; //manager.Add(sprite); }