Jump to content

  • Log In with Google      Sign In   
  • Create Account

Calling all IT Pros from Canada and Australia.. we need your help! Support our site by taking a quick sponsored surveyand win a chance at a $50 Amazon gift card. Click here to get started!


Danicco

Member Since 18 Jan 2011
Offline Last Active Jun 03 2014 03:18 PM

Posts I've Made

In Topic: OpenGL UV Mapping and FBX Loading

22 March 2014 - 06:35 PM

Another example, probably better explained:

Example2_zps8473a260.jpg

 

The 3DS Max vertex data is upside down in my engine, and I'm guessing it's because the XYZ values in 3DS Max are left handed, and OpenGL is right handed right?

That's manageable, but the UV data is messed around too, and I noticed that the way I was even going on about mirroring textures is wrong because I was assuming a texture that covers the entire image, not just part of it.

 

I'm meaning that, in the example above, if I only put some texture color in the Purple area, and I mirror it horizontally with my current code, I'm just picking the UV values that correspond to the Red area in the texture, and that's wrong... I made this assuming 2D images and square textures and now that I'm loading directly from the FBX, it's not working for 3D models.

 

Using "1.0f - uv" values work for 2D planes, but not for 3D models...


In Topic: Skeletal Animation System

21 March 2014 - 02:25 PM

Okay, hopefully, my last post in this topic!

 

Finally got it to work perfectly! I had some trouble with bone's origin of rotation since I was using quaternions and had to adjust a few things...

 

In the end, I did:

class Skeleton
{
    public:
        //bunch of controls
    private:
        float _bonePositions[MAX_BONES * 3]; //Bone Local Position
        float _boneTranslations[MAX_BONES * 3]; //Bone Translate
        float _boneRotations[MAX_BONES * 4]; //Bone Rotation in Quat
}

The local position mostly never changes, but I had to use it to figure the point of each bone to center the rotation around it... and the shader:

#version 330 core
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec2 vertexUV;
layout(location = 2) in vec3 vertexNormal;
layout(location = 3) in vec4 boneIndexes;
layout(location = 4) in vec4 boneWeights;

out vec2 UV;

uniform mat4 transformationMatrix;

uniform vec3 bonePosition[64];
uniform vec3 boneTranslation[64];
uniform vec4 boneRotation[64];

void skinVertex(in vec3 vertexPosition, in vec3 bonePosition, in vec3 boneTranslation, in vec4 boneRotation, in float boneWeight, out vec3 updatedVertexPosition)
{
    vec3 rotationOrigin = vertexPosition - bonePosition;

    vec3 cross;
    cross.x = (boneRotation.y * rotationOrigin.z - rotationOrigin.y * boneRotation.z) * 2;
    cross.y = (boneRotation.z * rotationOrigin.x - rotationOrigin.z * boneRotation.x) * 2;
    cross.z = (boneRotation.x * rotationOrigin.y - rotationOrigin.x * boneRotation.y) * 2;

    vec3 crossQuat;
    crossQuat.x = boneRotation.y * cross.z - cross.y * boneRotation.z;
    crossQuat.y = boneRotation.z * cross.x - cross.z * boneRotation.x;
    crossQuat.z = boneRotation.x * cross.y - cross.x * boneRotation.y;

    cross.x = cross.x * boneRotation.w;
    cross.y = cross.y * boneRotation.w;
    cross.z = cross.z * boneRotation.w;

    updatedVertexPosition = vertexPosition + ((cross + crossQuat + boneTranslation) * boneWeight);
}

void main()
{
    vec3 skinnedVertex = vertexPosition;

    skinVertex(skinnedVertex, bonePosition[int(boneIndexes.x)], boneTranslation[int(boneIndexes.x)], boneRotation[int(boneIndexes.x)], boneWeights.x, skinnedVertex);
    skinVertex(skinnedVertex, bonePosition[int(boneIndexes.y)], boneTranslation[int(boneIndexes.y)], boneRotation[int(boneIndexes.y)], boneWeights.y, skinnedVertex);
    skinVertex(skinnedVertex, bonePosition[int(boneIndexes.z)], boneTranslation[int(boneIndexes.z)], boneRotation[int(boneIndexes.z)], boneWeights.z, skinnedVertex);	
    skinVertex(skinnedVertex, bonePosition[int(boneIndexes.w)], boneTranslation[int(boneIndexes.w)], boneRotation[int(boneIndexes.w)], boneWeights.w, skinnedVertex);

    gl_Position = transformationMatrix * vec4(skinnedVertex, 1);
	
    UV = vertexUV;
}

And it's working!

Working_zpse6fb3047.jpg

 

Many many many thanks to everyone, that's been a huge help!


In Topic: Skeletal Animation System

20 March 2014 - 12:19 PM

I'm not using the FBX SDK, but it's just because I had already made a FBX Loader when I found out about the SDK... I'm reading the ASCII FBX file, but my 3DS Max is quite old (2010) so the format might've changed a bit, or because it's not the SDK there's some differences on what you've said, but it's nothing troublesome to adapt (like having zeros in all translates/rotates channels, on each keyframe that there is another value change anywhere, even if my animation didn't use that channel).

 

After I found out about the SDK, since I don't plan on using the FBX files (I'll read the data and save in a format of my game files), I didn't implemented it and kept using the old loader I had.

 

 

 


There doesn’t need to be an association between tracks and joints (or any other object that could be animated) at all.
The name tree simply allows to look up the target object and then the switch case allows to find which component the track will modify on that object, and once the track has a reference or pointer to that component you are done. No other associations need to exist.

 

That's a great concept, I didn't even had "names" in my scene (I was just going with everything by IDs, names were purely conventional and not necessary), and with this I think it'll become easier to have an animation of "Human Skeleton" and apply it to different humanoid skeletons as long as they have some/most bones names.

 

I've implemented everything and it looks great so far, but I just realized I'm back to a problem I was having when I posted this, which is the Update function, and I was trying to come up with a structure/system that didn't look as bad as this (current):

class PlayTrack
{
    public:
        Track* track;
        float* valueReference;
};

class PlayState
{
    public:
        void PlaySequence(wstring sequenceName);

        void Update(double updateTime);    
    private:
        Animation* _animation;

        vector<PlayTrack*> _tracks; //track instances, with the value refs assigned
        vector<Sequence*> _sequences; //an animation sequence defined by the code
        vector<double> _sequenceTimes; //the time of each sequence, I didn't make another class so I don't call "new" during the update loop
};

//In my game's main code, it looks like this:
void MyGame::Start()
{
    //Loading stuff
    Animation* animation = FBXLoader.GetAnimation("HUMAN");

    //Creating a new sequence of animation from frames 5 to 10 and naming it WALK
    //I'm using frames as time value, from the FBX I'm getting it's always set at 30 FPS but I'll convert it here depending on my update timer
    animation->AddSequence(L"WALK", 5, 10);

    Model* model = Resources.Load_Model(L"MyModel", L"MyAnimationName"); //and some other params

    //Here I'm linking this model's animation instance (PlayState) to the object it's supposed to animate
    //in this case, the model's skeleton
    Scene.Add(model);

    //It'll start playing an animation
    model->PlaySequence(L"WALK"); //will pass this to it's PlayState
}

void PlayState::PlaySequence(wstring& sequenceName)
{
    //Getting the sequence from the original animation, so all models share the same sequences
    Sequence* sequence = _animation->GetSequence(sequenceName);
    if(sequence != 0)
    {
        _sequences.push_back(sequence);
        _sequenceTimes.push_back( (double) sequence->frameStart );
    }
 
    //So I'll have for now a "WALK" only animation running, starting at frame 5, going till 10
}

//Everything's set up already, now the engine call the scene to update the animations with a double updateTime
//from the fixed time step impl., where I convert the frames to whatever my fixed time step update rate is
void PlayState::Update(double updateTime)
{
    //This is where I'm not happy with how it is

    //Updating all times for the playing sequences, this is a must
    for(unsigned int i = 0; i < _sequenceTimes.size(); i++)
    {
        _sequenceTimes[i] += updateTime;
    }

    //Now for each sequence playing...
    for(unsigned int i = 0; i < _sequences.size(); i++)
    {
        //Check all tracks
        for(unsigned int j = 0; j < _tracks.size(); j++)
        {            
            double currentTime = _sequenceTimes[i];

            KeyFrame* prevFrame = 0;
            KeyFrame* nextFrame = _tracks[j]->track->keyFrames[0];
            
            //Check all it's keyframes           
            for(unsigned int k = 1; k < _tracks[j]->track->keyFrames.size(); k++)
            {
                prevFrame = nextFrame;
                nextFrame = _tracks[j]->track->keyFrames[k];

                if(currentTime >= prevFrame->keyFrame && currentTime <= nextFrame->keyFrame)
                {
                    //Here I got the keyFrame pair I'm looking for
                    break;
                }
            }
        }
    }
}

I can't really save the current time and a pair of keyframes per "PlayTrack" (trackInstance) because there might be more than one sequence playing, so I'm having to loop through so many vectors... isn't there a more elegant (ie. smarter) solution than this?

 

I'm thinking in maybe moving the sequences elsewhere, and making each "PlayState" able to play a single sequence, but that wouldn't change much since all I'd be doing is moving the sequence loop to another place and copying the PlayState multiple times because of it.

 

Edit: More Code

Maybe I'm worried for nothing and this might not be a big issue but I can't help but worry "am I doing this right?" and if this is the only way it would be reassuring to listen so I don't think too much over it.


In Topic: Skeletal Animation System

18 March 2014 - 07:20 PM


KeyFrame: A single {Time, Value} pair. Can act on an AnimatedSkeleton or anything else; just give it a reference to the value it modifies and another to a dirty flag.

 

I was going on using KeyFrame with 3 values because I'm using 3DS Max to get my models data, and from what I could get from the files is that if I translate anything on the X-axis, it would create a translate channel (track) for X, Y and Z (with zeros on the unused values).

But animating anything on screen is really great, I hadn't thought about it, thanks!

 

One question though, I'm supposed to have then an Animation class with a vector of tracks, and these tracks point to a value that they change, and each track has a vector of KeyFrames, the values at which time changes... I'm loading from a FBX file and pairing it with the base Skeleton I get from the file, so the reference values for each track are those bones (like Track #1 is translate X for Bone 1), but then I copy the skeleton to a "skeletonInstance" for the animated model, and the references would still be pointing to the original "pose skeleton".

 

How can I get to correctly assign the references without making the KeyFrame / Track classes specifically for the Bone/Skeleton structures?

 

For now I'm having each KeyFrame (changing to track in your structure) assigned to a bone index (int value, not ref), so I know which is which.

And this also means I have to change my loader... ugh!


In Topic: Skeletal Animation System

16 March 2014 - 01:06 PM


If I understand correctly, you design seems to tightly couple a number of distinct concepts that may lead to you duplicating a lot of data due to the denormalised schema. I think it's probably quite important to separate out the concepts of a Skeleton, an Animation and the current PlayState of an animation to factor out shared/reusable data.

 

Oh that's what I was thinking in, but I wasn't really getting the idea behind it and I was mixing what Animation and PlayState is, thanks for clarifying that for me.

 


Using frames and avoiding interpolation will most probably show you choppy animations, since the timing of your game loop is required to be absolutely stable. Moreover, it probably causes many more keyframes than are needed. And it hinders you from blending cyclic animations in general.

 

In the example I forgot about interpolation, but I didn't meant I wouldn't do it, I'm using a double as "frameTimer" and I'd multiply the value by that value (which should be between 0~1). Each update increases the "frameTimer" by a value depending on my "updates per second" timer.

 


Dealing with real keyframes at "arbitrary" time moments is not so bad, since the current pair of keyframes can be memorized in the playback speed. So yo just need to look forward, e.g. whether the current time delta has exceeded the later of the both keyframes.

 

Now it seems much more clearer how I can implement this, I wasn't really sure about the "PlayState" class and was trying to fit the Animation (dealing with it as if it wasn't a resource) with it and the code was getting just messy and confusing.

 

I'm only unsure if I should make the skeleton / bones as a scene object as well, or if I should leave them as only a reference to all "human models" in the scene for example.

I think it might not be so bad calculating and updating all bones' matrices even if I'm not really using them in the scene, and I think I might be able to use them for physics/collisions easier if they're all in the scene (I haven't even started physics so I'm not sure, I'm only trying to plan ahead how I'd do it).

Then implementing a "special case" when a game requires a bone to hold a children in the scene is looking bad since if I'm going to use them for anything else, it wouldn't be the "special" case anymore.

 

Again, many thanks for all the replies, I got a much clear vision of how I should deal with animations now.


PARTNERS