• Advertisement

C++ How to fix this timestep once and for all?

Recommended Posts

One of the biggest reasons why I haven't released my game is because of this annoying timestep issue I have.  To be frank, this game was poorly planned, poorly coded, and was originally written as a small tech demo and a mini-game.  Now it has evolved into a fully featured (and very messy code base of a) game.  If you thought Lugaru was bad, Looptil is far worse!  So what happens is that the delta is not really consistent.  Sometimes enemies don't spawn fast enough because the delta isn't even consistent at 60fps, which is a big reason why the game is broken.

static uint64_t last_time = 0;
uint64_t current_time = time_get_time(); //( get_current_time() * 1000.0f );

int fps_limit = 60;
float frame_time = float( current_time - last_time );

if( last_time != 0 )
	This->m_delta_speed = frame_time / ( 1000.0f / 60.0f );

And this is my timing function:

uint64_t time_get_time()
{
#ifdef _WINRT
	return GetTickCount64();
#endif
	
#if __ANDROID__	/* TODO: Fix std::chrono for Android NDK */
	uint64_t ms = 0;
	timeval tv;

	gettimeofday( &tv, NULL );

	ms = tv.tv_sec * 1000;
	ms += tv.tv_usec / 1000;

	return ms;
#else
	std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    std::chrono::system_clock::duration tp = now.time_since_epoch();
	std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(tp);
	return (uint64_t) ms.count();
#endif
}

Now I know some of you will cringe when you see GetTickCount64(), but that's the only function that gives me reliable results on Windows 10 (UWP) ports, so that's staying. 

One more thing to note here, my game has a badly written game loop.  It uses a switch statement, followed by draw_game_mode(), update_game_mode(), so I kinda screwed myself there.  I tried changing it, but it broke the game completely, so I left it in it's messy state.  Is it possible to simply just have a proper delta calculation function?  Because it's adjusting itself based on the current frame time.  This may not be the best of ideas, but it was something I whipped up because I needed to have this run okay when it goes down to 30fps without running half the speed.  This works in general, but it's innacurate and causes problems.

Any ideas?  Thanks.

Shogun

EDIT: Feel free to ask anything in case I missed a vital detail.  My lunch break is ending and it's time for me to go.  Thanks.

Share this post


Link to post
Share on other sites
Advertisement

Although I see that link shared alot, it actually made my timing issues worse for this particular game.  In the future, I'll be sure to follow that guide to avoid future headaches.

Also, I fixed the problem.  Instead of using frame times, I used my game's actual frame rate divided by 1000.  Now it works perfectly (so far).  L. Spiro is going to kill me if he reads this, but I just want this game to work!

Thanks.

Shogun

Share this post


Link to post
Share on other sites

Frame rate = Frames Per Second by most usual definitions. Or, Frames Per 1000 Milliseconds, if you will.

If your framerate is N frames per second, then it is also true that your framerate is N/1000 frames per millisecond. Frame time is milliseconds per frame, or seconds per frame / 1000.

It sounds like you just have a units/order-of-magnitude mixup in the original code, and your 1000 is adjusting for it.

Share this post


Link to post
Share on other sites
On 7/30/2017 at 11:43 PM, blueshogun96 said:

Although I see that link shared alot, it actually made my timing issues worse for this particular game.  In the future, I'll be sure to follow that guide to avoid future headaches.

Also, I fixed the problem.  Instead of using frame times, I used my game's actual frame rate divided by 1000.  Now it works perfectly (so far).  L. Spiro is going to kill me if he reads this, but I just want this game to work!

Thanks.

Shogun

You.

Dirty.

RAT!!

You didn’t make the game work, you just hid the problem under a rug.  It will work differently on various devices so I am not sure how this helps you release anything.

You don’t show the whole game loop.  What is This->m_delta_speed?
Are you accumulating time from 0 = launch of game?  Why the conversion to float?


L. Spiro

Share this post


Link to post
Share on other sites
On 30/07/2017 at 6:40 AM, blueshogun96 said:

 


static uint64_t last_time = 0;
uint64_t current_time = time_get_time(); //( get_current_time() * 1000.0f );

int fps_limit = 60;
float frame_time = float( current_time - last_time );

if( last_time != 0 )
	This->m_delta_speed = frame_time / ( 1000.0f / 60.0f );

 

Is that the real algorithm? You never update last_time in that algorithm.

On 30/07/2017 at 6:40 AM, blueshogun96 said:

Now I know some of you will cringe when you see GetTickCount64(), but that's the only function that gives me reliable results on Windows 10 (UWP) ports, so that's staying. 

 

Every Win10/UWP device supports the QueryPerformanceCounter/Frequency API - the normal way to do precision timing.

Milliseconds are shitty for game timing. If your loop frequency is 60Hz, then a millisecond timer is accurate to +/- 6%... What's worse is that GetTickCount64 says that it typically has 10-16ms accuracy (+/-60% to 96% error) :(

On 31/07/2017 at 4:43 PM, blueshogun96 said:

Also, I fixed the problem.  Instead of using frame times, I used my game's actual frame rate divided by 1000.  Now it works perfectly (so far).  L. Spiro is going to kill me if he reads this, but I just want this game to work!

 

Maybe you've got code that just happens to output a small value every frame, which is not actually a measurement of delta time, but happens to simply be some arbitrary number that's small enough to act as a plausible fixed timestep value.

e.g. if you simply hardcode an arbitrary delta, such as "m_delta_speed = 0.06f;" do you get similar results?

Share this post


Link to post
Share on other sites
On 8/4/2017 at 4:41 AM, L. Spiro said:

You.

Dirty.

RAT!!

You didn’t make the game work, you just hid the problem under a rug.  It will work differently on various devices so I am not sure how this helps you release anything.

You don’t show the whole game loop.  What is This->m_delta_speed?
Are you accumulating time from 0 = launch of game?  Why the conversion to float?


L. Spiro

Yes, now I am finding the flaws as they surface.  Sometimes after coming out of the background or a suspended state, the FPS calculation will spew a really high number and cause the game to move rapidly for one second, then go back to normal.  This will result in death many times for the user.  So yes, I dun f@#%ed up even more.

The entire gameloop is too large and is a complete mess (I'll never code a game this way ever again).  The delta_speed variable is a percentage that is multiplied against the entity's speed value so that it moves at an adjusted speed based on frame rates.  I am not accumulating time as I did not plan this thing ahead or even consider the need for time based movement when I originally wrote it.  Then when primitive counts started reaching the millions, frame rates dropped and then I realize "I dun screwed up".

 

On 8/4/2017 at 7:30 AM, Hodgman said:

Is that the real algorithm? You never update last_time in that algorithm.

Every Win10/UWP device supports the QueryPerformanceCounter/Frequency API - the normal way to do precision timing.

Milliseconds are shitty for game timing. If your loop frequency is 60Hz, then a millisecond timer is accurate to +/- 6%... What's worse is that GetTickCount64 says that it typically has 10-16ms accuracy (+/-60% to 96% error) :(

Maybe you've got code that just happens to output a small value every frame, which is not actually a measurement of delta time, but happens to simply be some arbitrary number that's small enough to act as a plausible fixed timestep value.

e.g. if you simply hardcode an arbitrary delta, such as "m_delta_speed = 0.06f;" do you get similar results?

The loop is updated further down.  I forgot to add that.

If milisecond timing is a bad design choice, then I will do a way with it pronto.  I wasn't aware of the poor accuracy, and if the margin of error is that great, then I'll most definitely stop using it.  I wrote that half arsed timing function out of laziness.  Speaking of high resolution timers, I'll need one that's portable to all three major OSes.  Which I did find here: http://roxlu.com/2014/047/high-resolution-timer-function-in-c-c--

/* ----------------------------------------------------------------------- */
/*
  Easy embeddable cross-platform high resolution timer function. For each 
  platform we select the high resolution timer. You can call the 'ns()' 
  function in your file after embedding this. 
*/
#include <stdint.h>
#if defined(__linux)
#  define HAVE_POSIX_TIMER
#  include <time.h>
#  ifdef CLOCK_MONOTONIC
#     define CLOCKID CLOCK_MONOTONIC
#  else
#     define CLOCKID CLOCK_REALTIME
#  endif
#elif defined(__APPLE__)
#  define HAVE_MACH_TIMER
#  include <mach/mach_time.h>
#elif defined(_WIN32)
#  define WIN32_LEAN_AND_MEAN
#  include <windows.h>
#endif
static uint64_t ns() {
  static uint64_t is_init = 0;
#if defined(__APPLE__)
    static mach_timebase_info_data_t info;
    if (0 == is_init) {
      mach_timebase_info(&info);
      is_init = 1;
    }
    uint64_t now;
    now = mach_absolute_time();
    now *= info.numer;
    now /= info.denom;
    return now;
#elif defined(__linux)
    static struct timespec linux_rate;
    if (0 == is_init) {
      clock_getres(CLOCKID, &linux_rate);
      is_init = 1;
    }
    uint64_t now;
    struct timespec spec;
    clock_gettime(CLOCKID, &spec);
    now = spec.tv_sec * 1.0e9 + spec.tv_nsec;
    return now;
#elif defined(_WIN32)
    static LARGE_INTEGER win_frequency;
    if (0 == is_init) {
      QueryPerformanceFrequency(&win_frequency);
      is_init = 1;
    }
    LARGE_INTEGER now;
    QueryPerformanceCounter(&now);
    return (uint64_t) ((1e9 * now.QuadPart)  / win_frequency.QuadPart);
#endif
}
/* ----------------------------------------------------------------------- */

Since this game is cross platform, it has to work on everything.  If nano seconds are the way to go, then I'll use that instead.

And yes, using the frame rate isn't really a reliable way to do this (it blew up in my face).  I found that using a fixed value will give me consistent results.  A fixed delta doesn't generate any issues for me. 

Shogun

Share this post


Link to post
Share on other sites

As a side note, in case it helps you (on some future project I guess): bullet (the physics API) ticked at constant rate, but it still allowed for frame-specific updates. OFC it only interpolated those between two known states. So it's has both predictable behavior and hi-frame-rate-butter-smooth goodness; apparently nobody noticed it's a tick late.

I tried something similar in an TD game I tried years ago I don't think you remember: the implication is that you have to correct for inconsistencies as an enemy spawned at 0.5 tick still has to be half-a-tick evolved and cannot be backwards interpolated at 0.3 ticks. Since the game wanted to be deterministic in nature I couldn't let players the chance to get different patterns due to hardware power. Ew! Hopefully you don't need this detail!

Share this post


Link to post
Share on other sites
On 10/08/2017 at 10:56 AM, blueshogun96 said:

  I found that using a fixed value will give me consistent results.  A fixed delta doesn't generate any issues for me. 

;(

Try it in a PC with a 144Hz monitor now..

Share this post


Link to post
Share on other sites

'Easy' fix: run your physics with a 720 Hz timestep. Iterate it 5 times per frame for 144Hz monitors/vsync, 12 times for a 60Hz monitor, and 24 times for a 30Hz monitor. No interpolation needed!

Share this post


Link to post
Share on other sites

Wow, didn't realize I had more responses to the thread...

Anyway, I'm fixed it "forrealzees" this time.  Using the roxlu portable nanosecond timer in place of my millisecond one, then converting the numerator from 1000 milliseconds to the appropriate number (1000*1000*1000), it appears to work fine this time.  Even without Vsync, ran nicely at 120+fps. 

It was a combination of a low resolution timer plus my own spawning code was causing some entities to spawn yet rapidly disappear!  Since it happens in the blink of an eye, it was a rather hard bug to catch until today.  So far, no more spawning issues!

Now to try it on my desktop Mac and PC, as well as mobile devices.

On 8/13/2017 at 2:52 PM, Hodgman said:

;(

Try it in a PC with a 144Hz monitor now..

If only I had one.  All of my monitors are 60hz only :/

Shogun.

Share this post


Link to post
Share on other sites

Why not use a high-precision timer?

You can look at mine (Timer.h, Timer.cpp) for example :) .

I always used this kind of timer when coding a game and it always gave me great result in the past.

Honestly, what's the point of fixed timestep except in some circumstance, and hard coded frames per seconds limits if you

can just use vsync to do the job for you? Just my 2 cents here...

Share this post


Link to post
Share on other sites
3 hours ago, Vortez said:

Honestly, what's the point of fixed timestep except in some circumstance, and hard coded frames per seconds limits if you

can just use vsync to do the job for you?

Vsync doesn't guarantee you a fixed frame duration - it guarantees you one of several frame durations that is a multiple of the hypothetical minimum, and that minimum can vary from one machine to another. That is a problem if you want consistent physics for all players.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By Martin H Hollstein
      Originally posted on Troll Purse development blog.
      Unreal Engine 4 is an awesome game engine and the Editor is just as good. There are a lot of built in tools for a game (especially shooters) and some excellent tutorials out there for it. So, here is one more. Today the topic to discuss is different methods to program player world interaction in Unreal Engine 4 in C++. While the context is specific to UE4, it can also easily translate to any game with a similar architecture.
      Interaction via Overlaps
      By and far, the most common tutorials for player-world interaction is to use Trigger Volumes or Trigger Actors. This makes sense, it is a decoupled way to set up interaction and leverages most of the work using classes already provided by the engine. Here is a simple example where the overlap code is used to interact with the player:
      Header
      // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "InteractiveActor.generated.h" UCLASS() class GAME_API InteractiveActor : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties InteractiveActor(); virtual void BeginPlay() override; protected: UFUNCTION() virtual void OnInteractionTriggerBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); UFUNCTION() virtual void OnInteractionTriggerEndOverlap(UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); UFUNCTION() virtual void OnPlayerInputActionReceived(); UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Interaction) class UBoxComponent* InteractionTrigger; } This is a small header file for a simple base Actor class that can handle overlap events and a single input action. From here, one can start building up the various entities within a game that will respond to player input. For this to work, the player pawn or character will have to overlap with the InteractionTrigger component. This will then put the InteractiveActor into the input stack for that specific player. The player will then trigger the input action (via a keyboard key press for example), and then the code in OnPlayerInputActionReceived will execute. Here is a layout of the executing code.
      Source
      // Fill out your copyright notice in the Description page of Project Settings. #include "InteractiveActor.h" #include "Components/BoxComponent.h" // Sets default values AInteractiveActor::AInteractiveActor() { PrimaryActorTick.bCanEverTick = true; RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root")); RootComponent->SetMobility(EComponentMobility::Static); InteractionTrigger = CreateDefaultSubobject<UBoxComponent>(TEXT("Interaction Trigger")); InteractionTrigger->InitBoxExtent(FVector(128, 128, 128)); InteractionTrigger->SetMobility(EComponentMobility::Static); InteractionTrigger->OnComponentBeginOverlap.AddUniqueDynamic(this, &ABTPEquipment::OnInteractionProxyBeginOverlap); InteractionTrigger->OnComponentEndOverlap.AddUniqueDynamic(this, &ABTPEquipment::OnInteractionProxyEndOverlap); InteractionTrigger->SetupAttachment(RootComponent); } void AInteractiveActor::BeginPlay() { if(InputComponent == nullptr) { InputComponent = ConstructObject<UInputComponent>(UInputComponent::StaticClass(), this, "Input Component"); InputComponent->bBlockInput = bBlockInput; } InputComponent->BindAction("Interact", EInputEvent::IE_Pressed, this, &AInteractiveActor::OnPlayerInputActionReceived); } void AInteractiveActor::OnPlayerInputActionReceived() { //this is where logic for the actor when it receives input will be execute. You could add something as simple as a log message to test it out. } void AInteractiveActor::OnInteractionProxyBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) { if (OtherActor) { AController* Controller = OtherActor->GetController(); if(Controller) { APlayerController* PC = Cast<APlayerController>(Controller); if(PC) { EnableInput(PC); } } } } void AInteractiveActor::OnInteractionProxyEndOverlap(UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) { if (OtherActor) { AController* Controller = OtherActor->GetController(); if(Controller) { APlayerController* PC = Cast<APlayerController>(Controller); if(PC) { DisableInput(PC); } } } }  
      Pros and Cons
      The positives of the collision volume approach is the ease at which the code is implemented and the strong decoupling from the rest of the game logic. The negatives to this approach is that interaction becomes broad when considering the game space as well as the introduction to a new interactive volume for each interactive within the scene.
      Interaction via Raytrace
      Another popular method is to use the look at viewpoint of the player to ray trace for any interactive world items for the player to interact with. This method usually relies on inheritance for handling player interaction within the interactive object class. This method eliminates the need for another collision volume for item usage and allows for more precise interaction targeting.
      Source
      AInteractiveActor.h
      // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "InteractiveActor.generated.h" UCLASS() class GAME_API AInteractiveActor : public AActor { GENERATED_BODY() public: virtual OnReceiveInteraction(class APlayerController* PC); }  
      AMyPlayerController.h
      // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/PlayerController.h" #include "AMyPlayerController.generated.h" UCLASS() class GAME_API AMyPlayerController : public APlayerController { GENERATED_BODY() AMyPlayerController(); public: virtual void SetupInputComponent() override; float MaxRayTraceDistance; private: AInteractiveActor* GetInteractiveByCast(); void OnCastInput(); }  
      These header files define the functions minimally needed to setup raycast interaction. Also note that there are two files here as two classes would need modification to support input. This is more work that the first method shown that uses trigger volumes. However, all input binding is now constrained to the single ACharacter class or - if you designed it differently - the APlayerController class. Here, the latter was used.
      The logic flow is straight forward. A player can point the center of the screen towards an object (Ideally a HUD crosshair aids in the coordination) and press the desired input button bound to Interact. From here, the function OnCastInput() is executed. It will invoke GetInteractiveByCast() returning either the first camera ray cast collision or nullptr if there are no collisions. Finally, the AInteractiveActor::OnReceiveInteraction(APlayerController*)  function is invoked. That final function is where inherited classes will implement interaction specific code.
      The simple execution of the code is as follows in the class definitions.
      AInteractiveActor.cpp
      void AInteractiveActor::OnReceiveInteraction(APlayerController* PC) { //nothing in the base class (unless there is logic ALL interactive actors will execute, such as cosmetics (i.e. sounds, particle effects, etc.)) }  
      AMyPlayerController.cpp
      AMyPlayerController::AMyPlayerController() { MaxRayTraceDistance = 1000.0f; } AMyPlayerController::SetupInputComponent() { Super::SetupInputComponent(); InputComponent->BindAction("Interact", EInputEvent::IE_Pressed, this, &AInteractiveActor::OnCastInput); } void AMyPlayerController::OnCastInput() { AInteractiveActor* Interactive = GetInteractiveByCast(); if(Interactive != nullptr) { Interactive->OnReceiveInteraction(this); } else { return; } } AInteractiveActor* AMyPlayerController::GetInteractiveByCast() { FVector CameraLocation; FRotator CameraRotation; GetPlayerViewPoint(CameraLocation, CameraRotation); FVector TraceEnd = CameraLocation + (CameraRotation.Vector() * MaxRayTraceDistance); FCollisionQueryParams TraceParams(TEXT("RayTrace"), true, GetPawn()); TraceParams.bTraceAsyncScene = true; FHitResult Hit(ForceInit); GetWorld()->LineTraceSingleByChannel(Hit, CameraLocation, TraceEnd, ECC_Visibility, TraceParams); AActor* HitActor = Hit.GetActor(); if(HitActor != nullptr) { return Cast<AInteractiveActor>(HitActor); } else { return nullptr; } }  
      Pros and Cons
      One pro for this method is the control of input stays in the player controller and implementation of input actions is still owned by the Actor that receives the input. Some cons are that the interaction can be fired as many times as a player clicks and does not repeatedly detect interactive state without a refactor using a Tick function override.
      Conclusion
      There are many methods to player-world interaction within a game world. In regards to creating Actors within Unreal Engine 4 that allow for player interaction, two of these potential methods are collision volume overlaps and ray tracing from the player controller. There are several other methods discussed out there that could also be used. Hopefully, the two implementations presented help you decide on how to go about player-world interaction within your game. Cheers!
       
       
      Originally posted on Troll Purse development blog.
    • By mister345
      Hi, I'm on Rastertek series 42, soft shadows, which uses a blur shader and runs extremely slow.
      http://www.rastertek.com/dx11tut42.html
      He obnoxiously states that there are many ways to optimize his blur shader, but gives you no idea how to do it.
      The way he does it is :
      1. Project the objects in the scene to a render target using the depth shader.
      2. Draw black and white shadows on another render target using those depth textures.
      3. Blur the black/white shadow texture produced in step 2 by 
      a) rendering it to a smaller texture
      b) vertical / horizontal blurring that texture
      c) rendering it back to a bigger texture again.
      4. Send the blurred shadow texture into the final shader, which samples its black/white values to determine light intensity.
       
      So this uses a ton of render textures, and I just added more than one light, which multiplies the render textures required.
       
      Is there any easy way I can optimize the super expensive blur shader that wouldnt require a whole new complicated system?
      Like combining any of these render textures into one for example?
       
      If you know of any easy way not requiring too many changes, please let me know, as I already had a really hard time
      understanding the way this works, so a super complicated change would be beyond my capacity. Thanks.
       
      *For reference, here is my repo, in which I have simplified his tutorial and added an additional light.
       
      https://github.com/mister51213/DX11Port_SoftShadows/tree/MultiShadows
       
    • By Sung Woo Yeo
       
      Guys, I've spent a lot of time to load skeletal animation
      but  It is very difficult...
      I refer to http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html
      but I didn't get the results I wanted
       
      Please Help Me
       
      This is my codes
       
      void LoadAnimation::BoneTransform(float time, vector<XMFLOAT4X4>& transforms) { XMMATRIX Identity = XMMatrixIdentity(); float TicksPerSecond = (float)(m_pScene->mAnimations[0]->mTicksPerSecond != 0 ? m_pScene->mAnimations[0]->mTicksPerSecond : 25.0f); float TimeInTicks = time*TicksPerSecond; float AnimationTime = fmod(TimeInTicks, (float)m_pScene->mAnimations[0]->mDuration); ReadNodeHeirarchy(AnimationTime, m_pScene->mRootNode, Identity); transforms.resize(m_NumBones); for (int i = 0; i < m_NumBones; ++i) { XMStoreFloat4x4(&transforms[i], m_Bones[i].second.FinalTransformation); } } void LoadAnimation::ReadNodeHeirarchy(float AnimationTime, const aiNode * pNode, const XMMATRIX& ParentTransform) { string NodeName(pNode->mName.data); const aiAnimation* pAnim = m_pScene->mAnimations[0]; XMMATRIX NodeTransformation = XMMATRIX(&pNode->mTransformation.a1); const aiNodeAnim* pNodeAnim = FindNodeAnim(pAnim, NodeName); if (pNodeAnim) { aiVector3D scaling; CalcInterpolatedScaling(scaling, AnimationTime, pNodeAnim); XMMATRIX ScalingM = XMMatrixScaling(scaling.x, scaling.y, scaling.z); ScalingM = XMMatrixTranspose(ScalingM); aiQuaternion q; CalcInterpolatedRotation(q, AnimationTime, pNodeAnim); XMMATRIX RotationM = XMMatrixRotationQuaternion(XMVectorSet(q.x, q.y, q.z, q.w)); RotationM = XMMatrixTranspose(RotationM); aiVector3D t; CalcInterpolatedPosition(t, AnimationTime, pNodeAnim); XMMATRIX TranslationM = XMMatrixTranslation(t.x, t.y, t.z); TranslationM = XMMatrixTranspose(TranslationM); NodeTransformation = TranslationM * RotationM * ScalingM; } XMMATRIX GlobalTransformation = ParentTransform * NodeTransformation; int tmp = 0; for (auto& p : m_Bones) { if (p.first == NodeName) { p.second.FinalTransformation = XMMatrixTranspose( m_GlobalInverse * GlobalTransformation * p.second.BoneOffset); break; } tmp += 1; } for (UINT i = 0; i < pNode->mNumChildren; ++i) { ReadNodeHeirarchy(AnimationTime, pNode->mChildren[i], GlobalTransformation); } }  
      CalcInterp~ function and Find~ function are like a tutorial
      (http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html)
       
      I think that I'm doing the multiplication wrong
      but I don't know where it went wrong
      If you want, i wall post other codes.
       
       here is my result
      (hands are stretched, legs are strange)

       
      and it is ideal result

    • By Ward Correll
      I include the source code from what I am playing with. It's an exercise from Frank Luna's DirectX 12 book about rendering a skull from a text file. I get a stack overflow error and the program quits. I don't know where I went wrong it's messy programming on the parts I added but maybe one of you masterminds can tell me where I went wrong.
      Chapter_7_Drawing_in_Direct3D_Part_II.zip
    • By mister345
      Hi guys, so I have about 200 files isolated in their own folder [physics code] in my Visual Studio project that I never touch. They might as well be a separate library, I just keep em as source files in case I need to look at them or step through them, but I will never actually edit them, so there's no need to ever build them.
      However, when I need to rebuild the entire solution because I changed the other files, all of these 200 files get rebuilt too and it takes a really long time.
      If I click on their properties -> exclude from build, then rebuild, it's no good because then all the previous built objects get deleted automatically, so the build will fail.
      So how do I make the built versions of the 200+ files in the physics directory stay where they are so I never have to rebuild them, but
      do a normal rebuild for everything else? Any easy answers to this? The simpler the better, as I am a noob at Visual Studio settings. Thanks.
  • Advertisement