Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Getting a hold of the rotation from the 3x3 section of a 4x4  (Read 5462 times)

0 Members and 2 Guests are viewing this topic.

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Getting a hold of the rotation from the 3x3 section of a 4x4
« Reply #15 on: April 03, 2011, 10:26:13 pm »
Quote from: "Laurent"
Quote
Hmm how do you mean? Don't I do number one? When the matrix is requested I update the matrix by first creating the rotation matrix and then the position and last the scale.

I was talking about the Orientation class, not the higher-level one.


Ah okay. Well hmm... Yeh the SetRotation function must be removed as it won't work properly with scale for instance. the SetScale function should be named just simply Scale instead. I'll look over my Orientation class if there's anything else misleading.

PS: Don't miss my edit on last post. It works now :D
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Getting a hold of the rotation from the 3x3 section of a 4x4
« Reply #16 on: April 03, 2011, 10:32:40 pm »
Great :)

Why don't you create a project for it? It looks bigger than just sources to share on a wiki.

Out of curiosity, what does the threading stuff includes?
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Getting a hold of the rotation from the 3x3 section of a 4x4
« Reply #17 on: April 03, 2011, 10:58:02 pm »
Quote from: "Laurent"
Great :)

Why don't you create a project for it? It looks bigger than just sources to share on a wiki.

Out of curiosity, what does the threading stuff includes?


Well there's some background to the threading if you think my design choices are weird.

I haven't tried it on any more advanced data structure than a simple text string but it works to a 100% :)

Simplified list of the classes

Code: [Select]

Looper
 ^--- Synchro
          ^---Output
                 ^---MessageList <- Message
          ^---Input
                 ^---MessageList <- Message



Explaination of implementation:
It includes an adaptation of your sf::Thread class that handles synchronization and looping, I call it Threading::Looper at a loss of better names. A Synchronization object per Threading::Looper which is the only allowed way to communicate with it. You can see if it's done with it's current "frame", tell it to start another frame or exit entirely. This object also handles the synchronization( duh it's name ) between the threads. Each Threading::Synchro object have an input object and an output object. These objects work pretty much the same but they got two different purposes so to make it as fool proof as possible I separate them to two different classes. These classes work with a message list filled with instances of Threading::Message which is simply a base class you should inherit from and define what ever data you want to transfer here(I know I like to over abuse inheritance, but I'm a ruby guy :D). Synchronization is implemented as a "one-way" street. If you tell thread A to synch with thread B then the output message list in thread A will be switched with the input message list in thread B. The new message list in thread A's output will also be cleared so it's empty when you work with it.

Also a lot of asserts inserted for really stupid stuff like if a message list would be used for input AND output at the same time the thing will simply stop and tell you "Ah! No can do!" but it's stuff that should not happen if you use the library straight out of the box.

 I also might add a Task class with a Task pool to the whole shebang. To be used as "Find a path from here to there using this data" and check every now and then "Done yet?" And if true then retrieve the result. When the result is retrieved the task is marked for being allowed to be assigned a new task. Alternate way to see it: Dedicate a whole thread for one function call. Give the function arguments and instead of waiting for the return value, you'll come back later when you got time to see if it's done yet.

Example with a producer thread and a consumer thread:
Code: [Select]
class TextMessage : public Threading::Message
{
public:
    static TextMessage *Create( const std::string &aString )
    {
        TextMessage *object = new TextMessage();
        if( object != NULL && object->Init( aString ) == true )
        {
            return object;
        }
        delete object;
        return NULL;
    }

    const std::string &GetString() const
    {
        return myString;
    }
private:
    bool Init( const std::string &aString )
    {
        if( Threading::Message::Init() == false )
            return false;

        myString = aString;
        return true;
    }

    std::string myString;
};

class MyProducer : public Threading::Looper
{
public:
    static MyProducer *Create()
    {
        MyProducer *object = new MyProducer();
        if( object != NULL && object->Init() == true )
        {
            return object;
        }
        delete object;
        return NULL;
    }
private:
    void Frame()
    {
        GetSynchro()->GetOutput()->GetList()->AddElement( TextMessage::Create( "Hello world!" ) );
    }
};

class MyConsumer : public Threading::Looper
{
public:
    static MyConsumer *Create()
    {
        MyConsumer *object = new MyConsumer();
        if( object != NULL && object->Init() == true )
        {
            return object;
        }
        delete object;
        return NULL;
    }
private:
    void Frame()
    {
        const Threading::MessageList *inputList = GetSynchro()->GetInput()->GetList();
        for( unsigned int index = 0, end = inputList->NumElements(); index < end; index++ )
        {
            TextMessage *message = inputList->GetElement< TextMessage >( index );
            std::cout << message->GetString() << std::endl;
        }
    }
};

int main()
{
    MyProducer *producer = MyProducer::Create();
    MyConsumer *consumer = MyConsumer::Create();
    producer->Launch();
    consumer->Launch();

    bool running = true;
    sf::Clock clock;
    while( running == true )
    {
        if( producer->GetSynchro()->IsFinished() == true && consumer->GetSynchro()->IsFinished() == true )
        {
            producer->GetSynchro()->SynchWith( consumer->GetSynchro() );
            producer->GetSynchro()->StartThread();
            consumer->GetSynchro()->StartThread();
        }

        if( clock.GetElapsedTime() > 10 )
        {
            running = false;
            producer->GetSynchro()->ExitThread();
            consumer->GetSynchro()->ExitThread();
        }
    }

    producer->Terminate();
    consumer->Terminate();
    return 0;
}

When run it takes 100% on two of my cores which gives us lock-less parallelism( the consumer thread is not running at 100% because of std::cout ) :D Though here the frame amount is equal between the threads, this is not a must but if we let the faster thread run again before the second is done we need to handle the event when the second thread is overrun with data.

Also as you might notice, I use the Create-Init pattern though this is probably on subject to change as it's getting annoying to work with. Unless I can come up with a good template way to do it with macros or template class.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio