Step by Step Skeletal Animation in C++ and OpenGL, Using COLLADA PART 2

Level: Beginner to Intermediate

Before you start reading the implementations part, if you haven’t read the first part of this tutorial(s), which explains COLLADA documents in detail, you should follow the link below.

Part 1: COLLADA documents

You should have seen the following structure. In part 1

1)     Reading and Understanding COLLADA documents. (high level overview of COLLADA)

2)     Actual Implementations in C++ using OpenGL, of what we learn in Part 1

The one that your are reading now is the second part which has further two parts,

1)     Implementation part related to the Exporter for COLLADA

2)     Implementation part related to the skeletal animation in C++ using OpenGL

As far as the implementation of skeletal animation is concerned, we will Use OpenGL and C++, but the exporter which is used to export Data from COLLADA documents into my own Binary format (.CBA), I have written in C# (C Sharp). I could have written that in C++, but I was too lazy to write my own implementation of XML readers, while C# has very good implementation for that. And the free API for XML parsing (tinyXML) has a lot of issues which I was not really ready for. So I wrote my COLLADA exporter in C# and I create my binary file format which I call CBA files, from my exporter. CBA means COLLADA Binary Assets 🙂 and later I import this file in C++ using a CBA reader API. Now this introduced a lot of problems for me, like I have to maintain almost similar code twice once in C# for my exporter and Once in C++ for my importer. So it would be better that you don’t use my exporter and write your own Exporter in what ever language you prefer. And that would also help you understand the COLLADA documents in depth.

Part 2.1:

Implementation of Exporter for COLLADA, written in C#

Implementation of Skeletal Animation in COLLADA documents

As we have discussed in the introduction part, this tutorial is split in to two parts, I assume you have already read first one general introduction to COLLADA documents which is irrespective of any programming language Part 1: COLLADA documents.  Now we would define the structure in which we can read the COLLADA document. Please bear in mind that this exporter which I have written in C# is one of my worst ever codes, I wrote everything very quick and didn’t had any time to plan and design before code. So you will see a lot of hacks every where 🙂 but it is of course recommended that you write your own exporter. One other thing you should remember is that, this part of part 2 will try to read the COLLADA document but will not change the structure (schema) of the data; every thing is read as it is from COLLADA, and when we will write our custom format out of it, we will just read those things which are really necessary.

Reading Geometry Data from COLLADA document
Click here to go to: Implementation section in Part 1 for this section of Part 2

In the introduction section of part 1, we discussed the following libraries and nodes which are related to this section and which will be parsed and used,

<library_geometries>

<geometry>

<mesh>

<souce>

<technique_common>

<float_array> and <NAME_array>

<accessor>

<param>

<triangles>

<vertices>

<input>

<p>

Now you might know that some of the nodes are part of the Core COLLADA, which means, that they can appear in many places and many libraries in COLLADA. So you should define a structure for those nodes with common names so that they can be used for all kinds of purposes, for example a <source> node can be used for Vertices, Animation, Texture Coordinates and Vertex Weights or any other kinds of data. This is something that I forgot in my C# implementation, and later I was not able to re-factor 🙂 Remember my hacky bits of code :).

So if I were to define a class in which I can read the Geometry data of a COLLADA document I would do something like follows.

class COLLADA
{
private:
    GeometryLibrary    m_GeometryLibrary;
};
 

Where GeometryLibrary would be defined as follows.

 
class GeometryLibrary
{
    Vector<Geometry>    m_Geometries;
};
 
And now we define Geometry as follows.
 
class Geometry
{
    Mesh                m_Mesh;
};

The rest of the Libraries are not important at this point so we will not discuss them. All the other types of classes which are needed to store different nodes from COLLADA are listed as follows. And this is the simplest implementation you can make. I am not considering optimizations and inheritance etc. and there might be a lot of opportunities for restructuring and optimizations. For example as we know a source can have one type of array node, which could be <float_array>, <NAME_array> or any other type of array, in my implementation I am using different classes for each, you might want to create one class called Array or BaseArray and then derive each type of Array from it with specialize values.

//----------------------------------------------//
class Float_Array
{
    unsigned int        m_Count;
    string              m_ID;
    float               *m_Floats;
};
//----------------------------------------------//
class Name_Array
{
    unsigned int        m_Count;
    string              m_ID;
    string              *m_Names;
};
//----------------------------------------------//
class Param
{
    string              m_Name;
    string              m_Type;
};
//----------------------------------------------//
class Accessor
{
    string              m_Source;
    unsigned int        m_Count;
    unsigned int        m_Stride;
    Vector<Param>       m_Params;
};
//----------------------------------------------//
class Technique_Common
{
    Accessor            m_Accessor;
};
//----------------------------------------------//
class Source
{
    string              m_ID;
    Float_Array         m_Float_Array;
    Name_Array          m_Name_Array;
    Technique_Common    m_TechniqueCommon
};
//----------------------------------------------//
class Input
{
    string              m_Semantic;
    string              m_Source;
    string              m_Offset;
    string              m_Set;
};
//----------------------------------------------//
class Vertices
{
    string              m_ID;
    Vector<Input>       m_Inputs;
};
//----------------------------------------------//
class P
{
    unsigned int         m_Count;
    unsigned short       *m_Indices;
};
//----------------------------------------------//
class Triangles
{
    unsigned int        m_Count;
    string              m_Material;
    Vector<Input>       m_Inputs;
    P                   m_P;
};
//----------------------------------------------//
class Mesh
{
    Vector<Source>      m_Sources;
    Vertices            m_Vertices;
    Vector<Triangles>   m_Triangles;
};
//----------------------------------------------//

Now using those files we will store the Geometry data from COLLADA documents in a COLLADA Class Object. How you can read all those nodes is another story, you can either use C#’s XML parsers or use TinyXML or any other XML parser to load and parse COLLADA documents, you can also write your own XML parser if you have enough time. But I would suggest using an existing one rather writing your own, since the goal is to read COLLADA documents not XML files.

By now you should have all the Data related to displaying the model in 3D scene, you can start from <triangles> node and render all the triangles using OpenGL.

Reading Texture filename from COLLADA document

Click here to go to: Implementation section in Part 1 for this section of Part 2

In the introduction section of part 1, we discussed the following libraries and nodes which are related to this section and which will be parsed and used,

<library_images>

<image>

<init_from>

Its all again up to you how you want to read the texture file name, once you know where to find it. In the simplest form I would create a class for LibraryImages as well in the COLLADA Class and read the <image> in to it and so on. So the refined implementation for Class COLLADA will become as follows.

class COLLADA
{
private:
    GeometryLibrary     m_GeometryLibrary;
    ImagesLibrary       m_ImagesLibrary;
};
 

Where ImagesLibrary would be defined as follows.

 
class ImagesLibrary
{
    Vector<Image>       m_Images;
};
 
And now we define Image as follows.
 
class Init_From
{
    string              m_Filename;
};
 
class Image
{
    Init_From           m_Init_From;
};
Reading Materials from COLLADA document
Click here to go to: Implementation section in Part 1 for this section of Part 2

In the introduction section of part 1, we discussed the following libraries and nodes which are related to this section and which will be parsed and used,

<triangles>

<library_materials>

<material>

<instance_effect>

<library_effects>

<effect>

<phong> or <blin>

<profile_COMMON>

<technique>

<ambient>

<diffuse>

<specular>

<emission>

<shininess>

<transparency>

<color>

If you have read the previous sections of this part 2, and introduction part for this section you should be able to define the structure for this section by yourself, so I will not discuss it, since its getting repeated.

Reading Skeleton from COLLADA document
Click here to go to: Implementation section in Part 1 for this section of Part 2

In the introduction section of part 1, we discussed the following libraries and nodes which are related to this section and which will be parsed and used,

<library_visual_scenes>

<node>

<instance_controller>

<skeleton>

<visual_scene>

<matrix>

In the introduction part we discussed how to read the skeleton from <visual_scene> so I assume you should be able to define the structure for reading that data. But I used another approach myself. Which I think is the simplest way of reading Skeleton from COLLADA documents. And before discussing that, you need to read the next section in the introduction part.

Reading Skinning information from COLLADA document
Click here to go to: Implementation section in Part 1 for this section of Part 2

In the introduction section of part 1, we discussed the following libraries and nodes which are related to this section and which will be parsed and used,

<library_controllers>

<controller>

<skin>

<source>

<param>

<accessor>

<technique_common>

<NAME_array>

<float_array>

<node>.

<vertex_weights>

<input>

<vcount>

<v>

What I do for reading the skeleton from COLLADA documents is that I read the <controller>, and for all the Bone SIDs I check in the Visual Scene and find his parent and Joint Matrix, there, and I read the Inverse Bind matrix from the <controller>. And that’s all what we need. As you might remember we took an assumption that all the joints must be attached to the skin. In that case you don’t have to read the <instance_controller> node in the <visual_scene> and you can read Bone IDs from <controller> and find them in <visual_scene>. It require a little work to find the node in <visual_scene> and find his parent etc, but once you have started working with COLLADA nodes it should not be hard for you.

Reading Animation data from COLLADA document
Click here to go to: Implementation section in Part 1 for this section of Part 2

In the introduction section of part 1, we discussed the following libraries and nodes which are related to this section and which will be parsed and used,

<library_animations>

<animation>

<source>

<sampler>

<channel>

<visual_scene>

By now you should be quite an expert to define the structure for loading this data into it. But I would also give you a hint. Your COLLADA Class should look as follows, after reading all those sections.

class COLLADA
{
private:
    GeometryLibrary     m_GeometryLibrary;
    ImagesLibrary       m_ImagesLibrary;
    EffectsLibrary      m_EffectsLibrary;
    MaterialLibrary     m_MaterialLibrary;
    ControllerLibrary   m_ControllerLibrary;
    AnimationLibrary    m_AnimationLibrary;
    VisualSceneLibrary  m_VisualSceneLibrary;
};
 

Where AnimationLibrary would be defined as follows and all the other libraries must have been defined by you.

 
class AnimationLibrary
{
    Vector<Animation>   m_Animations;
};
 
And now we define Animation as follows.
 
class Animation
{
    string              m_ID;
    Vector<source>      m_Sources;
    Vector<sample>      m_Samples;
    Vector<channel>     m_Channels;
};

And now you should be able to define “sample” and “channel” classes. You can also write a structure where you do some other processing already on these <animation> nodes, and only keep the list of channels, where you reference the sampler targeted by this channel and then in “sample” you save references to the <sources> that are targeted or used by that sample. This processing we have to do sooner or later so it’s your choice when and where you want to do it. But as we discussed in the beginning of this part, that we will not change the structure of COLLADA but read as it is so you might not want to do it now.

Please not that I am not giving you actual code for reading from COLLADA documents, since that depends on what language you use to read XML files. If you have read the first part of these tutorials and you have created the structure properly, you should be able to read the data very easily using any XML parser. So I will not go in that much detail of implementation. And will let you do the job yourself.

Once we have finished reading the COLLADA document, we are ready to write the CBA file, which will be explained in the following section, in case you don’t want to write CBA file you can write your own “what ever” format and then read it accordingly.

CBA file format

The CBA file format is a very easy and simple to read and write file format. Geometry and skeletal data i.e. Vertex Weights etc, is saved in index form, which means, the whole data is saved once in a long floats array and then that float array is referenced with indices from the places where the data is needed. This saves space when you don’t want to save repeated vertex attributes for example. In a typical 3D model one vertex can be used by many triangles, and instead of saving that vertex many times for each triangle, its better to save it once and save its index for each triangle. That’s how all the data is saved in COLLADA and CBA file will use the same structure since it saves a lot of space as well as sending this data to OpenGL is also easy and efficient.

The CBA file format header

You can see in figure 1, how the header for CBA file looks.

Figure 1: Header of CBA file 

The structure of the header, 96 bytes in total, in source code is as follows

class CCBAHeader  

{

public:

     // CBA Main Chunk contains information about all other chunks (32 Bytes in Total)

     class CCBAMainChunk

     {

     public:

          unsigned int  m_MagicNumber;               // Always CBA0

          unsigned int  m_ChunkID;                   // Must be 0 

          unsigned int  m_Version;                   // Version initial 1, In this version only supports GeometryChunk

          unsigned int  m_NoOfSubChunks;             // Total Number of Chunks

          unsigned int  m_HasAnimation_HasSkeleton;  // LowBytes = Animation, HighBytes = Skeleton

          unsigned int  m_FirstChunkOffset;          // From where does the First Chunk Starts

          unsigned int  m_FileSize;                  // Total number of Bytes in the File

          unsigned int  m_ExtraData;                 // Can be any number of Bytes after this bytes

     };

    

// Contains the Bind Position Geometry Data in CBA (40 Bytes in Total)

     class CCBAGeometryChunk

     {

     public:

          unsigned int  m_TotalNoOfTriangles;        // Total Triangles

          unsigned int  m_ChunkID;                   // Must be 1 

          unsigned int  m_NoOfTriangleGroups;        // Number of Triangle Groups Categorized by Material

          unsigned int  m_TrianglesDetails;          // 1 = Only Vertices, 2 = Vertices + Normals, 3 = Vertices + Normals + TextureCoords

          unsigned int  m_DataOffset;                // Actual Data Starts from this Offset

          char          m_TextureFileName[20];       // Texture files name (.jpg,.png,.tga,.bmp)  

     };

 

     // Contains the Animation Data in CBA (24 Bytes in Total)

     class CCBAAnimationChunk

     {

     public:

          unsigned int  m_NoOfAnimations;            // Total Animations Keyframes

          unsigned int  m_ChunkID;                   // Always 2

          unsigned int  m_NoOfKeyframes;             // Total Animations Keyframes

          float         m_StartTime;                 // Start Time of the animation

          float         m_TotalTime;                 // End time or total time of the animation

          float         m_FramesPerSecond;           // Frames Per second to render

     };

 

private:

     CCBAMainChunk      m_MainChunk;                // The Main Chunk of CBA file

     CCBAGeometryChunk  m_GeometryChunk;            // The Geometry Chunk of CBA file

     CCBAAnimationChunk m_AnimationChunk;           // The Animation Chunk of CBA file

};

Immediately, after the header is finished, the actual data of the CBA file format starts.

Figure 2: Data section of CBA file

As you can see the data section of the CBA file format is very simple. The first four elements are the 4 arrays we need which are saved in index form.

First one is the Vertices data, which says number of vertices in a 4 byte integer, and the actual data in 4 byte floats array.

Second one is the Normals data, which says number of Normals in a 4 byte integer, and the actual data in 4 byte floats array.

Third one is the Texture Coordinates data, which says number of Texture Coordinates in a 4 byte integer, and the actual data in 4 byte floats array.

Fourth one is the Vertex weights data, which says number of Vertex Weights in a 4 byte integer, and the actual data in 4 byte floats array.

After that we have the triangle group’s data, we already know how many triangle groups we have from the header so for each triangle group we save its number of triangles in a 4 bytes unsigned integer and second we save its material which is 4, 4 component vectors and 2 floats. In total 72 bytes for material. After that we save the triangles indices for each triangle, which are 3 unsigned shorts (1 for each vertex) per each attribute. So for a triangle which specifies Vertex, Normal and Texture Coordinate, we save 3 * 3 = 9 indices.

After the triangles data we write the Skeleton data, first we write the bind shape matrix for the skeleton. Then for each Joint we write its Parent ID, Joint Matrix, (which is called Bind matrix in the figure) and its inverse bind matrix. Remember we are not writing the Bone ID itself, in the skeleton, which can be considered as the number/index of the bone we read, so the first bone we read gets an ID of 0, the second one gets an ID of 1 and so on.

After the skeleton we have the weighted vertices data. For each vertex from the vertices source in the Geometry data section, we have to specify its weight towards any bone. So for each vertex we write the number of bones affecting this vertex, and then for each bone affecting this vertex, we write the Joint ID/Bone ID and the weight towards that bone.

And at the end we write the Animations key frame data. As you might have noticed that the animation nodes are targeting Joints from the skeleton and this was one of our assumptions that only skeletal animation is supported and not backed animations or vertex animation. So for each Bone/Joint targeted by the animations from the library animations we write it’s Bone ID and then its number of key frames, which consists of “time” and a Joint Matrix, which is called “transform” in the figure.

And that’s the whole CBA file format. In the next part you will learn how to create this Character in OpenGL scene that we saved in CBA files, how to connect it to the skeleton and how to animate it.

Part 2.2:

Implementation part; skeletal animation in C++ using OpenGL

Implementation of Skeletal Animation in C++

At last we are here 🙂 for which we were waiting. This part of the tutorials is the most important of all the other parts we have read so far. We will first try to write the implementation for loading the CBA file that we wrote before in C#. You can also download this CBA loading API from downloads section of this website.

The API has a CCBA class which handles loading and displaying of the CBA files, which looks like follows.

class CCBA
{
public:
      CCBA(void);
      ~CCBA(void);
 
      // Some of the Functions are excluded from this text for the sake of simplicity
        void      Draw();
        bool      Update(unsigned long a_MiliSeconds);
        void      SetupSkeleton(int a_Frame);
        void      SetupBindPose();
        void      ReadCBA(string a_FileName);
    
protected:
        void      ReadHeader(CExport *a_File, string a_FileName);
        void      ReadArray(CExport *a_File, float **a_Destination,unsigned int &a_Size);
        void      ReadTriangles(CExport *a_File);
        void      ReadSkeleton(CExport *a_File);
        void      ReadAnimations(CExport *a_File);
 
        void      WriteCBA(string a_FileName);
        
        void      CalculateBound();
        void      ConvertToArrays();
 
    private:
        // Only the most important member variables are shown here 
        CCBAHeader                 *m_Header;             // Header (Contains information about the file)
        CGeometryData              *m_GeometryData;       // Common data in the Mesh (List of Vertices/Normals/TexCoords)
        CSkeletonData              *m_SkeletonData;       // Skeleton Data used for animation
        Vector<CTriangleGroup*>    *m_TrianglesGroups;    // Individual Triangle Groups Separated By Material Data (Just Indices and Material)
    };
 

In the CCBA class the most important member variables are m_Header, m_GeometryData, m_SkeletonData and m_TriangleGroups the rest of the stuff is provided for the sake of completeness. As the names suggests, m_Header contains the Header, m_GeometryData will contain the Geometry of the Character, m_SkeletonData will contain the Joints Hierarchy, and m_TriangleGroups contains all the Triangle groups which are separated by Material, by the COLLADA Exporter from StudioMax.

 

The ReadCBA function of CCBA class looks like this.

 

void CCBA::ReadCBA( string a_FileName )
{
    CExport *File = new CExport(0,a_FileName);
 
    this->ReadHeader(File, a_FileName); // Read Header
    this->ReadArray(File, &this->m_GeometryData->m_VerticesArray, this->m_GeometryData->m_VerticesArraySize); // Read Points
    this->ReadArray(File, &this->m_GeometryData->m_NormalsArray, this->m_GeometryData->m_NormalsArraySize); // Read Normal
    this->ReadArray(File, &this->m_GeometryData->m_TextureCoordsArray, this->m_GeometryData->m_TextureCoordsArraySize); // Read Texture Coordinates
 
    if (65536 & this->m_Header->m_MainChunk.m_HasAnimation_HasSkeleton)
        this->ReadArray(File, &this->m_GeometryData->m_VertexWeightsArray, this->m_GeometryData->m_VertexWeightsArraySize);// Read Weights Data
 
    this->ReadTriangles(File); // Read Triangles Data
 
    if (65536 & this->m_Header->m_MainChunk.m_HasAnimation_HasSkeleton)
    {
        this->ReadSkeleton(File); // Read Skeleton Data
        this->ReadAnimations(File); // Read Animations Data
        this->SetupInverseBindAttributes(); // Extra Processing for setting up for Skinning
    }
 
    delete File;
    
    this->ReadClipsInformation(a_FileName); // Read Animation Clips
 
    this->CalculateBound(); // Calculates Bounding Sphere
 
    if (this->m_Header->m_MainChunk.m_Version == 1) // CBA Version 1 is changed to 2
    {
        this->ConvertToArrays();
        this->WriteCBA(a_FileName);
        this->DuplicateSkinnedData();
    }
    else
        this->DuplicateBackupData();
 
    this->FillVertexBufferObject(); // Makes it Ready to be rendered 
    this->FillIndexBufferObject();  // Makes it Ready to be rendered
    this->SetupTexture(); // Sets up Texture and loads
}

You can see that the function is quite simple; it’s just reading the sections that we discussed before. For example it reads header, and all arrays, and then reads Triangles etc. One thing that I would like to explain here is that the exporter that we discussed before write a CBA version 1.0, which means all the data is saved as it is as we read from COLLADA. In ReadCBA function we check if the CBA version is 1.0 then we convert it to CBA Version 2.0. And before doing that, ConvertToArrays() is called, which takes all the arrays from CBA and makes them ready to be used with OpenGL Vertex Buffers and Index Buffers. The Difference between these two types is that, for example we have one triangle in COLLADA and it has 3 Attributes per vertex. So each vertex of a triangle in COLLADA has 1 Index per Attribute, and 3 indices for 3 attributes. While OpenGL Vertex Buffers can only read One Index per vertex for any number of attributes. For that purpose we have to do some extra processing on the data arrays to shuffle them so that each vertex used in a triangle has same Index for all its attributes from the attributes sources. And then we resave this new CBA file as Version 2.0. If you don’t understand this process, then don’t worry and keep on reading because you need this step only if you want to render the mesh using OpenGL vertex and index buffers. If you want to render everything in immediate mode then you don’t have to worry about that.

The rest of the functions are self explanatory, each one of them reads the corresponding section from CBA files, and if I try to explain each and every one of them separately it will easily get very boring.

The main purpose of ReadCBA is to read the CBA file and fill the data structures that we created for saving the Character data. We have already discussed the header structure of CBA file. Now we will discuss the rest of the data structures that we save.

CGeometryData	*m_GeometryData;       // Common data in the Mesh (List of Vertices/Normals/TexCoords)

CGeometryData class contains all the Data that we need for the Character other then Skeleton and Animations data. And it looks like follows.

class CGeometryData

{

public:

     CGeometryData(void);

     ~CGeometryData(void);

     //Functions for this class are removed

private:

     float                        *m_VerticesArray;                     // All the Vertices

     float                        *m_SkinnedVerticesArray;              // All the Skinned Vertices

     float                        *m_NormalsArray;                      // All the Normals

     float                        *m_SkinnedNormalsArray;               // All the Skinned Normals

     float                        *m_TextureCoordsArray;                // All the Texture Coordinates

     float                        *m_VertexWeightsArray;                // All the Vertex Weights

     Vector<CVertexInfluence*>    *m_VertexInfluences;                  // Vertices Influences

 

     unsigned int                 m_VerticesArraySize;

     unsigned int                 m_NormalsArraySize;

     unsigned int                 m_TextureCoordsArraySize;

     unsigned int                 m_VertexWeightsArraySize;

};

We will read all the Vertices, Normals, Texture coordinates and Vertex Weights arrays in this m_GeometryData pointer. If you see we also have Duplicated copies of both the Vertices array and Normals array. These copies are used during skinning and will be explained later. Since the Vertex Texture coordinates and vertex weights never change during skinning, we don’t need copies of them.

Apart from all that, we have a list of CVertexInfluence pointers for each model. This is the list where we save the data regarding which bone is influencing which vertex with how much weight. The structure of CVertexInfluence is as follows.

class CVertexInfluence

{

public:

     CVertexInfluence(void);

     ~CVertexInfluence(void);

 

private:

     unsigned int       m_NoOfInfluences;      // Total Number of Influences

     unsigned int       *m_Weights;             // Weights Array

     int                *m_Joints;              // Joints Array

};

 

The next thing in CCBA is;

 
CSkeletonData           *m_SkeletonData;       // Skeleton Data used for animation
 
This is where the skeleton data is saved and the structure of the CSkeletonData is as follows.

 

class CSkeletonData

{

public:

     CSkeletonData(void);

     ~CSkeletonData(void);

 

private:

     unsigned int  m_NoOfBones;          // Total Number of Joints in Skeleton

     unsigned int  m_NoOfKeyframes;      // Another Copy of the No Of Key frames of animation

     CMatrix4f     *m_BindShapeMatrix;   // Bind Shape Matrix

     CBone         **m_Bones;            // All the bones

     CBone         *m_RootBone;          // Root bone reference to one of the Bone in the m_Bones

};

Here we save all the bones and the bones contain the hierarchy information. We have the Bind Shape Matrix, and a bone count. How each bone is structures is as follows.

class CBone

{

public:

     CBone(void);

     ~CBone(void);

private:

     int           m_ID;                  // ID of this bone

     int           m_ParentID;            // Parent ID of this bone

     CMatrix4f     *m_JointMatrix;        // The Bind Pose Matrix

     CMatrix4f     *m_InverseBindMatrix;  // The Inverse Bind Pose Matrix

     CMatrix4f     *m_WorldMatrix;        // The World Matrix

     CMatrix4f     *m_SkinningMatrix      // The Matrix Used for calculations

     unsigned int  m_ChildCount;          // Number of Children

     Vector<int>   *m_Children;           // Children of this bone

     unsigned int  m_NoOfKeyframes;       // No Of key frames of animation for this bone

     CKeyframe     **m_Keyframes;         // All Key frames for this Bone’s animation

};

Here we have the Bone ID, Parent Bone ID, Joint Matrix, Inverse Bind Matrix, all the Child bone IDs and all the key frames for this bone. World Matrix and Skinning Matrix are created and changed at run time when we run the animation, so they are just convenience buffers. Each key frame is a pair of Transformation (Joint Matrix) and time.

class CKeyframe

{

public:

     CKeyframe(void);

     ~CKeyframe(void);

 

private:

     float          m_Time;                // Time of this key frame

     CMatrix4f      *m_Transform;          // Transformation of this Key frame

};

 

The next very important thing in CCBA is;

 
Vector<CTriangleGroup*> *m_TrianglesGroups;// Individual Triangle Groups Separated By Material Data (Just Indices and Material)
 
The Structure of a CTriangleGroup is as follows.
 
class CTriangleGroup

{

public:

CTriangleGroup(void);

     ~CTriangleGroup(void);

 

     // The functions for this class are removed

 

private:

     CTriangle     *m_Triangles;

     CMaterial     *m_Material;

     unsigned int  m_NoOfTriangles;

};

This class is used for saving the triangles data from CBA file as well as the material information for each triangle group. For the sake of completeness the structure of CTriangle is also presented, which is used to save 9 indices for 3 vertices and their 3 attributes of each vertex of a triangle.

class CTriangle

{

public:

     CTriangle(void);

     ~CTriangle(void);

 

     // The functions for this class are removed

 

private:

 

     unsigned short     m_VerticesIndex[3];

     unsigned short     m_NormalsIndex[3];

     unsigned short     m_TexturesIndex[3];

};

And that’s all the data structures that we need to read the Character in. Now all what we have to do is to, use this data and make our character animate. Which is done half in setting up the skeleton SetupSkeleton() and half in SetupBindPose().

How skeletal Animation works?

If you have come so far you might already know that so far we have saved data for the character in 3 Categories, one category is the Geometry data of the Character which is saved in m_GeometryData and m_TriangleGroups, second category is the skeleton data, which is saved in m_SkeletonData, and the Third Category is the animation data which is saved within the bones inside the m_SkeletonData. The first category of Geometry data can be used alone to draw the character on screen. The pose that you will see is called the Modeling pose, in which the character was modeled. Please refer to the following figure.

Figure 3: Modelling Pose of a Character

All you have to do to draw this Pose is to render all the triangles from all the triangle groups (m_TriangleGroups) with texture applied.

The second category can be used to draw the skeleton in Bind Pose, which is the pose when the skeleton was attached to the skin.

Figure 4: Skeleton in Bind Pose

You can see in this here that the skeleton is ready to be used to transform the vertices of the Modeling pose to bring the Character in this pose. The process goes like this.

Figure 5: Process of Binding Skeleton to the Skin

The model is given to us in Modeling Pose Just like shown in Figure 5.1, we have also setup the skeleton in the Bind pose like shown in Figure 5.2, we need to transform all the vertices of the model in Figure 5.1 using the skeleton from Figure 5.2 to get the shape of Figure 5.3, this is done with the Skinning equation given later in the text, and then we render the model using textures and materials as shown in Figure 5.4.

The transformation for each bone is calculated by multiplying its Joint Matrix with the parent Bone’s World matrix. An example is given in the following figure.

Figure 6: Deriving the skeleton world matrices

In this figure the World matrix for the red bone is calculated. We always start from the root bone, since the root bone doesn’t have any parent; its world matrix becomes its joint matrix. Next we pick the next bone in the hierarchy, we get its world matrix from multiplication of the parent bone’s (root bone) world matrix (M1W) with this bone’s Joint Matrix (M2j), and this world matrix is called M2in the figure. Now we move to the next bone (red bone) and to calculate its world matrix we multiply its parent bone’s World matrix (M2W) with the red bone’s Joint matrix (M3j) and we get the Red bone’s World Matrix called (M3W). This process is repeated for each bone, taking its parent bone world matrix and multiplying its own join matrix with it, and then saving the result in its own world matrix. As you can see this process must be started from the root bone, so that we don’t have dirty world matrices while we go down.

In this model most of the vertices are influenced by more then one bone, and the influence is denoted by the weight associated with each vertex toward each bone that influences it. Without this the animation looks very rigid. Example of vertices affected by only one bone is given as follows.

Example of vertices affected by more then one bone is given as follows.

Figure 7: Vertices only effected by one bone

Example of vertices affected by more than one bone is given as follows.

Figure 8: Vertices effected by more then one bone

In the following figure you can see how the vertex weights are distributed over the vertices. Red Color vertices means high influence from the red bone, while blue color means less influence from the selected Bone (red bone), the colors in between red and blue are used for weight values between zero and one.

Figure 9: Vertices affected with different weights by the red bone

In the following sections you will see how the weights of each bone affecting a vertex are accumulated to get the final vertex position.

And the Final and Third category is the Animations data. We use the animation data to move the Skeleton of the character in different poses and then use that new pose generated by the animation data to transform the vertices of the character and draw in new pose. So all what the animation data do is to animate the skeleton and we use the animated skeleton to animate our character.

Figure 10: Animation data is applied to the skeleton to animate the skeleton

Here we can see that the Bind pose skeleton is transformed by different key frame transforms from the animation data, to define different poses. And then these poses are used to drive the skin, and transform the vertices of the character.

This was all the theory behind skeletal animation, how it is done using our CBA file data is given in the following sections.

In SetupSkeleton() we make the skeleton ready for next pose, the body of the function is as follows. And then we use that pose to setup our vertices in the new pose which is done in SetupBindPose().

void CCBA::SetupSkeleton(int a_Frame)

{

// Update the tree of bones

static CStack<int> BonesStack;

BonesStack.Push(this->m_SkeletonData->m_RootBone->m_ID);

      while (!BonesStack.Empty())
     {

          unsigned int CurrentBone = BonesStack.Pop();

          assert(CurrentBone != -1  && "Current Bone is Null");

 

          CMatrix4f WorldMatrix = *this->m_SkeletonData->m_Bones[CurrentBone]->m_JointMatrix;

 

          if (this->m_SkeletonData->m_Bones[CurrentBone]->m_NoOfKeyframes > 0/* && frame > 0*/)

          {

              assert(a_Frame < (int)this->m_SkeletonData->m_Bones[CurrentBone]->m_NoOfKeyframes && "Invalid Key frame");

 

              float InBetween = (float)(this->m_AnimationTime * (float)this->m_SkeletonData->m_NoOfKeyframes / this->m_Header->m_AnimationChunk.m_TotalTime);

              InBetween -= a_Frame;

 

              if (a_Frame <  (int)this->m_SkeletonData->m_Bones[CurrentBone]->m_NoOfKeyframes - 1)

              {

                   WorldMatrix = Interpolate(*this->m_SkeletonData->m_Bones[CurrentBone]->m_Keyframes[a_Frame]->m_Transform,

                                                          *this->m_SkeletonData->m_Bones[CurrentBone]->m_Keyframes[a_Frame + 1]->m_Transform,InBetween);

              }

              else

                   WorldMatrix = *this->m_SkeletonData->m_Bones[CurrentBone]->m_Keyframes[a_Frame]->m_Transform;

 

          }

 

          if (this->m_SkeletonData->m_Bones[CurrentBone]->HasParent())

              WorldMatrix = WorldMatrix * *this->m_SkeletonData->m_Bones[this->m_SkeletonData->m_Bones[CurrentBone]->m_ParentID]->m_WorldMatrix;

 

          *this->m_SkeletonData->m_Bones[CurrentBone]->m_WorldMatrix = WorldMatrix;

          *this->m_SkeletonData->m_Bones[CurrentBone]->m_SkinningMatrix = *this->m_SkeletonData->m_Bones[CurrentBone]->m_InverseBindMatrix * WorldMatrix;

 

          // Handle its Children

          if (this->m_SkeletonData->m_Bones[CurrentBone]->HasChildren())

          {

              unsigned int NoOfChildren = this->m_SkeletonData->m_Bones[CurrentBone]->m_ChildCount;

              for (unsigned int Index = 0; Index < NoOfChildren; Index++)

              {

                   BonesStack.Push(this->m_SkeletonData->m_Bones[CurrentBone]->GetChildAt(Index));

              }

          }

     } // While

}

In very short and very simple, all this function is doing is to take the current frame Joint Matrix for the current bone and if it’s a root bone then save that Joint matrix as world matrix for the current bone, other wise take the parent bones World matrix and multiply this bone’s Joint matrix with it and then save the result as current bone’s World Matrix. We have to start this process from the Root bone so that we don’t have dirty world matrices from previous frames in the tree. This is why a Depth first Tree Traversal is used, using a Stack. Now for each bone we have a new World Matrix for the current frame of animation. And in the same function we use this World Matrix to derive the skinning matrix for the current bone, which is used in SetupBindPose() to do the skinning, which means to attach all the vertices with the skeleton and move them with the corresponding bones. If you see SetupBindPose() you will see in the beginning the skinning calculation equation. In that equation we need have (IBMi * JMi) which means we need to multiply a bone’s Inverse Bind matrix with its World matrix so that’s what is done in SetupSkeleton() and the result is saved in advance in m_SkinningMatrix for each bone, with this we don’t have to do this multiplication for each and every vertex we need to skin to the skeleton. One other thing which we can do before hand is the (v * BSM) which is the multiplication of each vertex with the Bind Shape matrix of the skeleton. So we do that once and then use the updated vertices. The actual skinning is done in the following function.

void CCBA::SetupBindPose()

{

     /*

     The skinning calculation for each vertex v in a bind shape is

     for i to n

          v += {[(v * BSM) * IBMi * JMi] * JW}

 

     • n: The number of joints that influence vertex v

     • BSM: Bind-shape matrix

     • IBMi: Inverse bind-pose matrix of joint i

     • JMi: Transformation matrix of joint i

     • JW: Weight of the influence of joint i on vertex v

 

     I have Got (v * BSM) and (IBMi * JMi) already multiplied since they are constants

     */

     rUsInt NumberOfVertices = this->m_GeometryData->m_VerticesArraySize / 3;

     for (rUsInt CurrentVertex = 0; CurrentVertex < NumberOfVertices; CurrentVertex++)

     {

          CVector3f TempVertex;

          CVector3f TempNormal;

          CVector3f TempNormalTransform;

 

          CVector3f Vertex(  this->m_GeometryData->m_VerticesArray[(CurrentVertex * 3)    ],

                                  this->m_GeometryData->m_VerticesArray[(CurrentVertex * 3) + 1],

                                  this->m_GeometryData->m_VerticesArray[(CurrentVertex * 3) + 2]);

 

          CVector3f Normal(  this->m_GeometryData->m_NormalsArray[(CurrentVertex * 3)    ],

                                  this->m_GeometryData->m_NormalsArray[(CurrentVertex * 3) + 1],

                                  this->m_GeometryData->m_NormalsArray[(CurrentVertex * 3) + 2]);

 

          float TotalJointsWeight = 0;

          float NormalizedWeight = 0;

 

          for (rUsInt CurrentInfluence = 0; CurrentInfluence < (*this->m_GeometryData->m_VertexInfluences)[CurrentVertex]->m_NoOfInfluences; CurrentInfluence++)

          {

 

              TempVertex    += ((Vertex *

                   *this->m_SkeletonData->m_Bones[(*this->m_GeometryData->m_VertexInfluences)[CurrentVertex]->m_Joints[CurrentInfluence]]->m_SkinningMatrix) *

                   this->m_GeometryData->m_VertexWeightsArray[(*this->m_GeometryData->m_VertexInfluences)[CurrentVertex]->m_Weights[CurrentInfluence]]);

 

              this->m_SkeletonData->m_Bones[(*this->m_GeometryData->m_VertexInfluences)[CurrentVertex]->m_Joints[CurrentInfluence]]->m_SkinningMatrix->RotateVector(Normal,TempNormalTransform);

 

                  TempNormal  += TempNormalTransform * this->m_GeometryData->m_VertexWeightsArray[(*this->m_GeometryData->m_VertexInfluences)[CurrentVertex]->m_Weights[CurrentInfluence]];

 

                  TotalJointsWeight += this->m_GeometryData->m_VertexWeightsArray[(*this->m_GeometryData->m_VertexInfluences)[CurrentVertex]->m_Weights[CurrentInfluence]];

          }

 

          if (TotalJointsWeight != 1.0f)

          {

              NormalizedWeight = 1.0f / TotalJointsWeight;

              TempVertex *= NormalizedWeight;

              TempNormal *= NormalizedWeight;

          }

 

          this->m_GeometryData->m_SkinnedVerticesArray[(CurrentVertex * 3)    ] = TempVertex.x;

          this->m_GeometryData->m_SkinnedVerticesArray[(CurrentVertex * 3) + 1] = TempVertex.y;

          this->m_GeometryData->m_SkinnedVerticesArray[(CurrentVertex * 3) + 2] = TempVertex.z;

 

          this->m_GeometryData->m_SkinnedNormalsArray[(CurrentVertex * 3)    ] = TempNormal.x;

          this->m_GeometryData->m_SkinnedNormalsArray[(CurrentVertex * 3) + 1] = TempNormal.y;

          this->m_GeometryData->m_SkinnedNormalsArray[(CurrentVertex * 3) + 2] = TempNormal.z;

 

     }

}

If you read the comments in the beginning of the functions it says how the skinning is done on this data that we have read so far.

The skinning calculation for each vertex v in a bind shape is

for i to n

     v += {[(v * BSM) * IBMi * JMi] * JW}

• n: The number of joints that influence vertex v

• BSM: Bind-shape matrix

• IBMi: Inverse bind-pose matrix of joint i

• JMi: Transformation matrix of joint i

• JW: Weight of the influence of joint i on vertex v

I have Got (v * BSM) and (IBMi * JMi) already multiplied since they are constants

As we have discussed already I have (v * BSM) and (IBMi * JMi) already multiplied from the SetupSkeleton() function, and we run a lope for all the vertices in the character and get both the current vertex as well as current normal (remember that the normal is also pre-multiplied with Bind Shape Matrix) and we run another nested lope for each bone (influence) influencing this vertex and take its weight and m_SkinningMatrix and multiply them with the current vertex, which is already multiplied with Bind shape matrix, and then save it back in the copy of the Vertices array (m_SkinnedNormalsArray) which we talked about when we created the data structure of CGeometryData. Now if we use this changed vertex and display the character, we will see the character in the current frame’s pose. This is the simple way of doing one frame of skinning for the character, if we want to animate it for the whole animation key frames, we must iterate for all the frames over time and call SetupSkeleton() and SetupBindPose() in that order.

As we discussed before if the time falls in between two key frames then we have to do interpolation on the two transforms for those two key frames. And then use the new value of transform to setup the skeleton. But once you have done the simple form of just running the character on all the key frames only, you can take the next step and do the interpolated animations or smooth animation. For that you might also like to save the transforms in quaternion instead of matrices.

This animation process can get as much complicated as you want it to be, in these implementations that I presented in this set of tutorials you will find the simple most animations you can achieve. You don’t even need to worry about any interpolations and such until you have your character changing pose from one frame to another. Once you have achieved that, you can go for improving your animation system and introduce things like, Smooth animation, Animations Instancing system, blending two animations, Layering two animations and doing Forward Kinematics on your animations etc and it never ends :).

I hope this tutorial will help people in working with COLLADA as well as doing skeletal animations, please don’t hesitate to bust my ass with your constructive comments and criticism. You can always reach me through my email address given in the contacts section of the website.

5,760 thoughts on “Collada Tutorial

  1. doersity.com

    Pretty section of content. I simply stumbled upon your weblog and in accession capital to say that I acquire actually enjoyed account your blog
    posts. Any way I’ll be subscribing for your feeds and even I achievement you get entry to consistently quickly.

    Reply
  2. pleksidepo.com

    I’m not sure where you’re getting your information, but great topic.

    I needs to spend some time learning much more or understanding more.
    Thanks for great info I was looking for this info for my mission.

    Reply
  3. sharmaspareparts.com

    When I initially left a comment I seem to have clicked the -Notify me when new comments are added- checkbox and
    now every time a comment is added I receive four emails with the same comment.

    Perhaps there is an easy method you are able to remove me from that service?
    Appreciate it!

    Reply
  4. 바카라사이트

    I’m really loving the theme/design of your website.

    Do you ever run into any web browser compatibility problems?
    A small number of my blog visitors have complained about
    my blog not operating correctly in Explorer but
    looks great in Opera. Do you have any solutions
    to help fix this problem?

    Also visit my blog post; 바카라사이트

    Reply
  5. 바카라사이트

    I’ve been browsing on-line more than 3 hours today, yet I never
    found any fascinating article like yours. It’s lovely
    price sufficient for me. Personally, if all site owners and bloggers made good content
    material as you did, the web can be a lot more useful than ever before.

    Also visit my web page; 바카라사이트

    Reply
  6. 우리카지노

    Hello, Neat post. There’s a problem together with your site in internet explorer, might test this?
    IE still is the market chief and a huge component of
    other people will omit your great writing because of this problem.

    Feel free to visit my web blog: 우리카지노

    Reply
  7. tracknmail.com

    I am now not certain where you’re getting your information, but great topic.
    I must spend some time finding out more or working out more.
    Thanks for wonderful info I used to be searching for this info for my mission.

    Reply
  8. Pat Mazza

    I’m extremely inspired with your writing skills and also with
    the format on your blog. Is that this a paid subject matter or
    did you customize it yourself? Anyway stay up the excellent high quality writing, it is uncommon to see a
    nice blog like this one these days..

    My web blog Pat Mazza

    Reply
  9. office furniture south africa

    I loved as much as you will receive carried out right here.
    The sketch is attractive, your authored material stylish.

    nonetheless, you command get bought an nervousness over that you wish
    be delivering the following. unwell unquestionably come further formerly again as exactly the same nearly a lot often inside case you
    shield this increase.

    Take a look at my blog :: office furniture south africa

    Reply
  10. 바카라사이트

    Unquestionably believe that which you stated.
    Your favorite justification seemed to be on the net the easiest thing to be aware of.

    I say to you, I definitely get irked while people think about worries that they just don’t know about.

    You managed to hit the nail upon the top and defined out the whole thing without having
    side-effects , people could take a signal. Will likely be
    back to get more. Thanks

    Also visit my web page; 바카라사이트

    Reply
  11. zarkin inc

    I’m not sure where you are getting your information, but good
    topic. I needs to spend some time learning much more
    or understanding more. Thanks for magnificent information I was looking for this
    info for my mission.

    my website: zarkin inc

    Reply
  12. 바카라사이트

    It’s a pity you don’t have a donate button! I’d definitely donate to this fantastic blog!
    I suppose for now i’ll settle for bookmarking and adding your
    RSS feed to my Google account. I look forward to new updates and
    will share this blog with my Facebook group.

    Chat soon!

    My page; 바카라사이트

    Reply
  13. zarkin inc

    Greetings from Los angeles! I’m bored to death at work so I
    decided to check out your site on my iphone during lunch break.
    I really like the info you provide here and can’t wait
    to take a look when I get home. I’m surprised at how fast
    your blog loaded on my mobile .. I’m not even using WIFI,
    just 3G .. Anyways, wonderful site!

    Review my web blog zarkin inc

    Reply
  14. Pat Mazza

    Amazing blog! Do you have any tips for aspiring writers?
    I’m planning to start my own website soon but I’m a little lost on everything.
    Would you propose starting with a free platform like WordPress or go
    for a paid option? There are so many options
    out there that I’m completely overwhelmed .. Any recommendations?
    Thanks!

    Also visit my web page … Pat Mazza

    Reply
  15. Furniture Store

    I’m truly enjoying the design and layout of your site.
    It’s a very easy on the eyes which makes it much more pleasant for me
    to come here and visit more often. Did you hire out a
    designer to create your theme? Great work!

    my web blog; Furniture Store

    Reply
  16. Galen

    With havin so much content do you ever run into any issues of plagorism or copyright violation? My site has
    a lot of completely unique content I’ve either authored myself or outsourced but it appears a lot of
    it is popping it up all over the web without my agreement.
    Do you know any techniques to help protect against content from being stolen? I’d truly appreciate it.

    Reply
  17. Konoha Lamp Company

    Woah! I’m really loving the template/theme of this
    website. It’s simple, yet effective. A lot of times it’s challenging to get that “perfect balance”
    between superb usability and visual appeal. I must say you’ve done a very good job with this.
    In addition, the blog loads extremely fast for me on Internet explorer.
    Exceptional Blog!

    Feel free to visit my blog … Konoha Lamp Company

    Reply
  18. 우리카지노

    Hello There. I found your blog the usage of msn. That is an extremely
    smartly written article. I will make sure to bookmark it and return to learn more of your useful info.
    Thanks for the post. I’ll definitely return.

    Reply
  19. codevina.com

    I blog frequently and I genuinely appreciate your information. This article has
    really peaked my interest. I am going to take a note of your site and
    keep checking for new information about once per week.
    I subscribed to your RSS feed as well.

    Reply
  20. Myrtle

    When someone writes an piece of writing he/she retains the thought of a user in his/her mind that how a user
    can understand it. So that’s why this piece of writing is perfect.
    Thanks!

    Reply
  21. phutungtauthuyen.com

    Hi there! Do you know if they make any plugins to help
    with Search Engine Optimization? I’m trying to get
    my blog to rank for some targeted keywords but I’m not seeing
    very good gains. If you know of any please share.
    Kudos!

    Reply
  22. yolkurye.com

    Wonderful blog! I found it while surfing around on Yahoo News.
    Do you have any suggestions on how to get listed
    in Yahoo News? I’ve been trying for a while but I never seem to get there!

    Appreciate it

    Reply
  23. clarkecolaw.com

    Attractive section of content. I just stumbled upon your
    weblog and in accession capital to assert that I acquire in fact enjoyed account your blog posts.
    Any way I’ll be subscribing to your feeds and even I achievement you access consistently quickly.

    Reply
  24. hindimints.com

    The other day, while I was at work, my sister stole my apple ipad and tested to see if it can survive a thirty foot drop, just so
    she can be a youtube sensation. My iPad is now broken and
    she has 83 views. I know this is completely off topic but
    I had to share it with someone!

    Reply
  25. heavyhittersboxinggym.com

    I am not certain the place you are getting your information,
    however great topic. I needs to spend some time studying much
    more or understanding more. Thanks for great info I used to be searching for this information for my mission.

    Reply
  26. hydrolysed collagen

    Write more, thats all I have to say. Literally, it seems
    as though you relied on the video to make your point. You clearly know what youre talking about, why waste your intelligence on just posting videos to your
    weblog when you could be giving us something informative to read?

    Stop by my webpage hydrolysed collagen

    Reply
  27. theangelhome.com

    I feel that is one of the such a lot important info for me.

    And i am satisfied studying your article. But should observation on some normal things, The website style is ideal, the articles is
    in point of fact great : D. Excellent job, cheers

    Reply
  28. ahwakora.com

    I’ve read several good stuff here. Certainly worth bookmarking for revisiting.
    I surprise how much effort you set to make this type of magnificent informative website.

    Reply
  29. threesixtysmallpop.com

    Have you ever thought about publishing an ebook or guest authoring on other blogs?
    I have a blog based on the same information you discuss and would
    love to have you share some stories/information. I
    know my readers would appreciate your work.
    If you are even remotely interested, feel free to send me an e-mail.

    Reply
  30. temisad.com

    Hi, I do believe this is a great web site. I stumbledupon it 😉 I
    am going to come back once again since I bookmarked it.

    Money and freedom is the greatest way to change, may you be rich and continue to help others.

    Reply
  31. patel1008.frimleymanorhotel.com/archives/3

    Have you ever thought about publishing an e-book or guest
    authoring on other websites? I have a blog centered on the
    same ideas you discuss and would really like to have you share some stories/information. I know my viewers would appreciate your
    work. If you are even remotely interested, feel free
    to send me an e mail.

    Reply
  32. Edna

    Wow, superb blog format! How long have you ever been blogging
    for? you make blogging glance easy. The whole
    glance of your web site is magnificent, as smartly as the content!

    Reply
  33. Cleo

    My brother suggested I might like this blog.
    He was entirely right. This post actually made my day.
    You can not imagine simply how much time I had spent for this info!

    Thanks!

    Reply
  34. tak-music.com

    excellent post, very informative. I wonder why the opposite experts of this sector do
    not notice this. You must proceed your writing.
    I’m confident, you’ve a huge readers’ base already!

    Reply
  35. cook1077.codeanger.com/46.html

    I’ve been browsing online more than 4 hours today, yet I never found any interesting article
    like yours. It is pretty worth enough for me. In my
    view, if all webmasters and bloggers made good content as you
    did, the internet will be a lot more useful than ever before.

    Reply
  36. jualcablegland.com

    hey there and thank you for your info –
    I’ve definitely picked up something new from right here.

    I did however expertise a few technical points using this web site, as I experienced to reload the site lots of times previous
    to I could get it to load correctly. I had been wondering if
    your web hosting is OK? Not that I’m complaining, but sluggish loading instances times will
    very frequently affect your placement in google and could damage your high-quality score if ads and marketing with Adwords.
    Anyway I’m adding this RSS to my email and can look
    out for a lot more of your respective intriguing content.
    Make sure you update this again very soon.

    Reply
  37. kajaikhao.com

    Hey there, I think your site might be having browser
    compatibility issues. When I look at your website in Chrome, it looks fine but when opening in Internet Explorer,
    it has some overlapping. I just wanted to give you a quick heads up!
    Other then that, great blog!

    Reply
  38. Tresoröffnung

    My brother suggested I would possibly like this web site.
    He used to be entirely right. This post actually made my day.
    You cann’t imagine simply how a lot time I had spent for this
    info! Thanks!

    Also visit my blog post … Tresoröffnung

    Reply
  39. intektekstil.com

    Hello There. I found your blog using msn. This is a very well written article.
    I’ll be sure to bookmark it and come back to read more
    of your useful information. Thanks for the post. I’ll definitely comeback.

    Reply
  40. doviramall.com

    My brother recommended I might like this blog.
    He was totally right. This put up actually made my day. You can not believe simply how a lot time I had spent for this info!

    Thank you!

    Reply
  41. behnamevent.com

    Have you ever thought about writing an e-book or guest authoring on other blogs?
    I have a blog centered on the same ideas you discuss and would
    love to have you share some stories/information.
    I know my visitors would value your work. If you’re even remotely interested, feel free to shoot me an e-mail.

    Reply
  42. fthkagit.com

    Its like you read my thoughts! You appear to know
    so much about this, such as you wrote the ebook in it or something.
    I believe that you just could do with some % to pressure
    the message home a bit, but instead of that, this is excellent blog.
    An excellent read. I will definitely be back.

    Reply
  43. Paramount Australia

    Today, while I was at work, my cousin stole my iphone and tested to see if it can survive a twenty
    five foot drop, just so she can be a youtube sensation. My iPad is now broken and she has 83 views.
    I know this is entirely off topic but I had to share it with someone!

    Here is my blog – Paramount Australia

    Reply
  44. laptop for

    Magnificent beat ! I wish to apprentice even as you amend your website,
    how could i subscribe laptop for a blog website?
    The account helped me a applicable deal. I had been tiny bit familiar of this your broadcast provided vivid clear concept

    Reply
  45. park city

    My brother suggested I might like this website.
    He was totally right. This post truly made my day. You
    can not imagine simply how much time I had spent for this info!
    Thanks!

    Feel free to visit my homepage; park city

    Reply
  46. Cottagecore fashion brands

    I believe everything composed was actually very reasonable.
    But, what about this? suppose you added a little content?
    I mean, I don’t want to tell you how to run your blog,
    but what if you added something that grabbed folk’s attention? I mean Collada Tutorial – waZim is a little boring.
    You ought to glance at Yahoo’s home page and note how they create
    post headlines to get people to open the links. You might add a
    video or a related picture or two to grab people excited about everything’ve
    got to say. Just my opinion, it would make your posts a little bit more interesting.

    Feel free to visit my web-site Cottagecore fashion brands

    Reply
  47. advancedbiostudies.com

    Excellent post. I was checking continuously this weblog and I am impressed!
    Extremely useful info particularly the ultimate phase 🙂 I take care of such info
    much. I was looking for this certain information for a very lengthy time.
    Thanks and good luck.

    Reply
  48. aledrissy.com

    Hi there! I know this is kinda off topic but I was wondering if
    you knew where I could get a captcha plugin for my comment
    form? I’m using the same blog platform as yours and I’m having problems finding one?

    Thanks a lot!

    Reply
  49. http://bookmarkextent.com/story9023875/how-can-i-get-me-some

    Web related principles and this site operates by sending out
    press releases so much. Materials dealing with eats away loads of this web site exhibits the system hash management.
    TCP/IP transmission management protocol/web protocol
    established exchanges are communicated to all their savings.

    Degree of management additionally makes it possible to enjoy bigger income is
    the biggest drop for cryptocurrencies. If sustained the one-day drop precipitously and a
    single laptop server or physical retailers Bitcoin cash.
    No government establishment or authorities controls over
    Bitcoin to financial balance and transaction.
    0.35 over the past year-the question the rally’s sustainability of Bitcoin commerce site.
    However with Bitcoin transactions has drawn strong opposition from the industry earning money within the information again. Bitpanda is predicated on basic and
    technical evaluation for trading decisions they usually have the most recent information. They often have the curiosity
    charges sudden automobile breakdown expense paying
    for connection pace. Charges and an open source software or a notice stating we live on-line.
    Cloud mi-ning contract for gold described above produce
    enough charges to maintain the dollar.

    Reply
  50. Dong

    Do you mind if I quote a few of your posts as long as I provide credit and sources back to your webpage?
    My website is in the very same area of interest as yours and my visitors would truly benefit from some of
    the information you provide here. Please let me know if this okay with you.
    Thank you!

    Reply
  51. Walker

    You really make it seem so easy with your presentation but I find this topic to be actually something which I think I would never understand.
    It seems too complex and extremely broad for me. I’m looking forward for your
    next post, I will try to get the hang of it!

    Reply
  52. edwards177.ilia-sanat.com/2.html

    What i do not realize is in truth how you’re not
    really much more neatly-preferred than you may be right now.
    You are so intelligent. You know thus significantly on the subject of
    this topic, made me personally imagine it from numerous numerous angles.
    Its like men and women aren’t involved unless it’s one thing to
    do with Girl gaga! Your own stuffs excellent. At all times
    handle it up!

    Reply
  53. โควิด 19

    Hi there I am so delighted I found your weblog, I really found
    you by mistake, while I was looking on Digg for something else, Anyways
    I am here now and would just like to say thank you for a incredible post and
    a all round exciting blog (I also love the theme/design), I
    don’t have time to look over it all at the moment but I have bookmarked it and also added your RSS feeds, so when I have time I will be back to read
    a great deal more, Please do keep up the excellent b.

    Here is my blog post; โควิด 19

    Reply
  54. Design hoodie from photo

    What i don’t understood is in truth how you’re not actually a lot
    more smartly-favored than you might be right now.
    You are very intelligent. You recognize thus considerably in terms of this topic,
    made me in my view believe it Design hoodie from photo a lot of numerous angles.

    Its like women and men are not fascinated until it’s something to
    do with Girl gaga! Your personal stuffs nice. At all
    times care for it up!

    Reply
  55. online clothing store

    Today, I went to the beach with my kids. I found a sea shell
    and gave it to my 4 year old daughter and said “You can hear the ocean if you put this to your ear.” She put the shell
    to her ear and screamed. There was a hermit crab inside and it pinched her ear.
    She never wants to go back! LoL I know this is entirely off topic but I had to tell someone!

    Here is my blog – online clothing store

    Reply
  56. women's clothes

    Hi! I know this is kind of off-topic however I needed to ask.
    Does operating a well-established website such as yours require a lot of work?
    I am brand new to running a blog however I do write in my
    diary everyday. I’d like to start a blog so I
    can share my personal experience and feelings online.

    Please let me know if you have any suggestions or tips for new aspiring blog owners.
    Thankyou!

    Also visit my web site … women’s clothes

    Reply
  57. mens clothing

    I really like your blog.. very nice colors & theme.
    Did you create this website yourself or did you hire someone to do it for you?
    Plz answer back as I’m looking to construct my own blog
    and would like to know where u got this from.
    thanks a lot

    my web-site; mens clothing

    Reply
  58. Webdesign

    Awesome blog! Do you have any suggestions for aspiring
    writers? I’m planning to start my own site soon but I’m a little lost on everything.

    Would you propose starting with a free platform like WordPress or go for
    a paid option? There are so many choices out there that I’m totally overwhelmed ..
    Any ideas? Bless you!

    Here is my web blog: Webdesign

    Reply
  59. estee lauder advanced night repair eye

    Hey there I am so glad I found your blog page,
    I really found you by mistake, while I was researching on Askjeeve for something else,
    Anyways I am here now and would just like to say thanks for a marvelous post and a all round entertaining blog
    (I also love the theme/design), I don’t have time to look over it all at the minute but I have book-marked it and also included your RSS feeds, so
    when I have time I will be back to read a lot more, Please do keep up the great jo.

    Here is my blog; estee lauder advanced night repair eye

    Reply
  60. Paramount Development

    Just wish to say your article is as amazing. The clarity for your publish is
    simply spectacular and i can think you are a professional in this subject.
    Well with your permission allow me to take hold of
    your feed to stay up to date with forthcoming post. Thank you one million and please continue the rewarding work.

    Here is my homepage: Paramount Development

    Reply
  61. best sleeping mask korean

    Hey there! This is kind of off topic but I need some advice from an established blog.
    Is it very difficult to set up your own blog? I’m not very techincal but I can figure things out pretty fast.
    I’m thinking about making my own but I’m not sure where to begin. Do you have any ideas or suggestions?
    Cheers

    My web page … best sleeping mask korean

    Reply
  62. Dakota

    Hеllo! Somеone in my Facebook grouρ shared
    tһiѕ site wіth us so I came to take a looқ. Ӏ’m definiteⅼy enjoying
    the information. I’m bookmarking and ѡill be tweeting
    thіs to mmy followers! Wonderful blog ɑnd terrific design.

    Feel free tօ visit my blog post: money online (Dakota)

    Reply
  63. wings io

    You testament notwithstanding require to in your Gamer ID/Username so that we
    can undergo on which GTA 5 record we’ve to grapple Pianoforte Motorcar
    5 Money and RP.

    Reply
  64. Linkbuilding

    I think this is one of the most significant info for me.
    And i am glad reading your article. But should remark on some general things, The site style is
    wonderful, the articles is really nice : D. Good job, cheers

    Feel free to surf to my blog … Linkbuilding

    Reply
  65. Knit set

    I loved as much as you will receive carried out right here.
    The sketch is tasteful, your authored subject matter stylish.
    nonetheless, you command get got an edginess over that you wish be delivering the following.
    unwell unquestionably come further formerly again as exactly the same nearly a lot often inside case you shield this increase.

    Stop by my blog post Knit set

    Reply
  66. daihatsupromoterbaru.com

    Great post. I was checking continuously this blog and I’m impressed!
    Extremely useful info particularly the last part 🙂 I care for such info a
    lot. I was seeking this certain info for a long time. Thank
    you and best of luck.

    Reply
  67. ชลิตา ราชนิยม

    What you published was actually very logical. However, what
    about this? what if you added a little information?
    I mean, I don’t want to tell you how to run your blog, but what if you added something to maybe get people’s attention? I mean Collada
    Tutorial – waZim is kinda boring. You might peek at Yahoo’s
    home page and note how they create article headlines to get viewers interested.
    You might add a video or a pic or two to get readers interested
    about what you’ve got to say. In my opinion, it could bring your blog a little livelier.

    Reply
  68. Summer apparel

    We’re a bunch of volunteers and opening a new scheme in our community.

    Your web site offered us with helpful information to work on. You’ve performed an impressive task and our entire group will probably
    be grateful to you.

    My website Summer apparel

    Reply
  69. Aksesoris komputer gaming

    ggwpstore adalah sebuah agen yang sangat lengkap aman dan terpercaya di indonesia,
    berlainan berasal dari agen – agen yang lainnya, ggwpstore menawarkan kemenangan yang benar-benar ringan dan pelayanan yang terlalu ramah,
    di percaya sebagai agen pkv games sejak 2015 sampai sementara ini pengguna / user terbukti terlampau meningkat brrasal
    dari th. ke tahun, Artinya jadi banyak pengguna khusuus
    nya orang indonesia memakai jasa sarana agen ggwpstore.

    Reply
  70. james663.littlepussy-hq.com/1.html

    Having read this I thought it was very informative.
    I appreciate you spending some time and effort to put
    this content together. I once again find myself personally spending a significant amount of time both reading and posting comments.
    But so what, it was still worth it!

    Reply
  71. island jerk

    Hello There. I found your blog using msn. This is a very well written article.
    I’ll be sure to bookmark it and come back to read more of your useful information. Thanks for
    the post. I’ll certainly comeback.

    my site – island jerk

    Reply
  72. spices set gift

    May I simply say what a relief to uncover somebody that genuinely understands what they are talking about over the internet.

    You definitely understand how to bring a problem to light and make it important.

    More and more people need to read this and understand this side of your story.
    I was surprised you are not more popular since you definitely have the spices set gift.

    Reply
  73. seasoning oxtail

    I’m amazed, I must say. Seldom do I encounter a blog that’s equally educative
    and entertaining, and let me tell you, you have
    hit the nail on the head. The problem is something that too
    few men and women are speaking intelligently about.
    I am very happy I found this in my search for something regarding this.

    Also visit my web site – seasoning oxtail

    Reply
  74. baking jerk chicken

    Hi! I understand this is somewhat off-topic but I needed to ask.

    Does building a well-established website like yours require a large amount of work?

    I’m completely new to operating a blog however I do write in my diary everyday.
    I’d like to start a blog so I can share my personal experience and thoughts online.
    Please let me know if you have any ideas or
    tips for brand new aspiring bloggers. Thankyou!

    my homepage – baking jerk chicken

    Reply
  75. baccarat.credit

    Thank you for some other fantastic post. Where else may anyone get that kind of information in such an ideal
    way of writing? I’ve a presentation subsequent week, and I’m on the search for such information.

    Reply
  76. 우리카지노

    This design is wicked! You certainly know how to keep a reader entertained.
    Between your wit and your videos, I was almost moved to start my
    own blog (well, almost…HaHa!) Great job. I really loved what you had to say, and more than that, how you presented it.

    Too cool!

    Here is my blog: 우리카지노

    Reply
  77. marketing agency

    Fantastic beat ! I wish to apprentice while you amend your site, how can i subscribe for a
    blog site? The account aided me a acceptable
    deal. I had been tiny bit acquainted of this your broadcast offered
    bright clear idea

    Look into my webpage: marketing agency

    Reply
  78. Paramount

    Wonderful work! That is the kind of information that are meant to be shared across the net.
    Disgrace on Google for no longer positioning this put up
    higher! Come on over and consult with my web site .
    Thanks =)

    my web blog; Paramount

    Reply
  79. 우리카지노

    Excellent blog right here! Additionally your site a lot up very fast!
    What host are you the use of? Can I get your affiliate hyperlink in your host?
    I want my web site loaded up as quickly as yours lol

    Feel free to surf to my web blog; 우리카지노

    Reply
  80. online marketing agency

    Fantastic blog! Do you have any tips and hints for aspiring writers?
    I’m hoping to start my own site soon but I’m
    a little lost on everything. Would you suggest starting with
    a free platform like WordPress or go for a paid option? There are so many choices out there
    that I’m totally confused .. Any suggestions? Appreciate it!

    Stop by my blog … online marketing agency

    Reply
  81. 우리카지노

    Appreciating the persistence you put into your website and in depth information you offer.
    It’s nice to come across a blog every once in a while that isn’t the same old rehashed information. Wonderful read!
    I’ve saved your site and I’m including your RSS feeds
    to my Google account.

    Check out my web page :: 우리카지노

    Reply
  82. 우리카지노

    I’m amazed, I must say. Seldom do I come across a blog that’s equally educative and entertaining, and without a doubt, you’ve
    hit the nail on the head. The problem is something that not enough people are speaking intelligently about.
    I am very happy that I stumbled across this in my search for something concerning this.

    Here is my web blog :: 우리카지노

    Reply
  83. Tyler Tivis Tysdal

    Definitely believe that which you said. Your favorite reason seemed to be on the internet the
    simplest thing to be aware of. I say to you, I definitely get annoyed while people think about worries that they just
    do not know about. You managed to hit the nail upon the top and also defined out
    the whole thing without having side effect , people
    could take a signal. Will likely be back to
    get more. Thanks

    my site – Tyler Tivis Tysdal

    Reply
  84. strappedshoetique.com

    Do you mind if I quote a couple of your posts as long as I
    provide credit and sources back to your site? My blog is in the very same niche as yours and my visitors would genuinely
    benefit from some of the information you provide here.
    Please let me know if this ok with you. Thanks!

    Reply
  85. Nora

    Everything is very open with a clear explanation of the issues.
    It was really informative. Your site is useful. Many thanks for sharing!

    Reply
  86. crazydealsforyou.com

    Simply desire to say your article is as amazing.

    The clarity to your publish is simply excellent and i could think you are a professional in this
    subject. Fine with your permission let me to grasp your RSS feed to stay up to date with imminent post.
    Thank you 1,000,000 and please keep up the gratifying work.

    Reply
  87. candy-cbd.com

    Right here is the right webpage for anybody who wishes to
    understand this topic. You realize a whole lot its almost
    hard to argue with you (not that I really would want to…HaHa).
    You definitely put a fresh spin on a subject that’s been discussed for many years.
    Wonderful stuff, just excellent!

    Reply
  88. sociowizard.com

    When I originally commented I clicked the “Notify me when new comments are added” checkbox and now each
    time a comment is added I get several emails with the same comment.

    Is there any way you can remove people from that
    service? Thanks a lot!

    Reply
  89. yarrak

    Definitely believe that which you stated. Your favorite
    justification appeared to be on the net the easiest thing to be aware
    of. I say to you, I certainly get irked while
    people consider worries that they plainly don’t know
    about. You managed to hit the nail upon the top and defined
    out the whole thing without having side effect ,
    people can take a signal. Will probably be back to get more.
    Thanks

    My page; yarrak

    Reply
  90. desikaddu.com

    Admiring the time and effort you put into your site and detailed information you offer.

    It’s awesome to come across a blog every once in a while that isn’t
    the same out of date rehashed information. Great read!

    I’ve saved your site and I’m including your RSS feeds to my Google
    account.

    Reply
  91. News

    It’s very effortless to find out any matter on web as compared to textbooks,
    as I found this piece of writing at this site.

    Here is my webpage: News

    Reply
  92. Seattle cubicles

    After I initially left a comment I seem to have clicked the -Notify me
    when new comments are added- checkbox and now whenever a comment is added
    I get four emails with the same comment. There has to be a means you can remove me from that
    service? Thank you!

    Here is my page Seattle cubicles

    Reply
  93. healthy living

    Hello are using WordPress for your site platform? I’m new to the blog world but I’m trying to get started and create my
    own. Do you require any coding expertise to make your own blog?
    Any help would be really appreciated!

    my web page: healthy living

    Reply
  94. in-situ balancing

    Hello there! This article could not be written much better!
    Looking through this post reminds me of my previous roommate!
    He always kept preaching about this. I most certainly will forward this article to him.
    Pretty sure he’ll have a great read. I appreciate you for sharing!

    Take a look at my blog post: in-situ balancing

    Reply
  95. unicume.com

    I’d like to thank you for the efforts you’ve put in writing
    this blog. I am hoping to view the same high-grade content by you later on as well.
    In fact, your creative writing abilities has encouraged me to get my
    own website now 😉

    Reply
  96. w88

    Hello to all, it’s truly a pleasant for me to pay a visit this web site, it includes precious Information.

    Take a look at my website – w88

    Reply
  97. w88

    My relatives always say that I am killing my time here at web,
    however I know I am getting familiarity daily by reading thes good articles or reviews.

    My web page: w88

    Reply
  98. Home Health Care

    Hi there would you mind sharing which blog platform you’re using?
    I’m going to start my own blog soon but I’m having a hard time making a decision between BlogEngine/Wordpress/B2evolution and Drupal.
    The reason I ask is because your layout seems different then most blogs and I’m looking for something completely unique.
    P.S My apologies for getting off-topic but I had to ask!

    my webpage – Home Health Care

    Reply
  99. w88

    That is a good tip especially to those fresh to the blogosphere.
    Short but very accurate info… Many thanks for sharing this one.
    A must read article!

    my blog w88

    Reply
  100. microfourthirdscameras.com

    Hi! Someone in my Facebook group shared this site with us so I came to look it over.
    I’m definitely loving the information. I’m book-marking
    and will be tweeting this to my followers! Great blog and brilliant
    design.

    Reply
  101. купить собачий фаллос

    Have you ever considered creating an e-book or guest authoring on other websites?
    I have a blog centered on the same ideas you discuss and
    would really like to have you share some stories/information. I know my
    subscribers would value your work. If you are even remotely
    interested, feel free to send me an e mail.

    Reply
  102. Simulation Training

    Woah! I’m really digging the template/theme of this
    website. It’s simple, yet effective. A lot of times it’s very hard to get that
    “perfect balance” between usability and visual appearance.
    I must say that you’ve done a very good job with this.
    Additionally, the blog loads extremely fast for me
    on Internet explorer. Exceptional Blog!

    My webpage: Simulation Training

    Reply
  103. w88

    After I initially left a comment I seem to have clicked on the -Notify me when new
    comments are added- checkbox and from now on each time a
    comment is added I recieve four emails with the exact same comment.

    Perhaps there is an easy method you are able to remove me from that service?
    Appreciate it!

    Check out my webpage :: w88

    Reply
  104. Hester

    It’s aɑn remarkable post designed fօr all the internet people; tһey will tɑke benefit from
    іt I am sure.

    Here іs my web-site … chanel online shop (Hester)

    Reply
  105. brown272.bashbircr.com/2020/12/----baccarat/

    Hmm it appears like your site ate my first comment (it was extremely
    long) so I guess I’ll just sum it up what I had written and say, I’m thoroughly enjoying your blog.
    I as well am an aspiring blog writer but I’m still
    new to the whole thing. Do you have any suggestions for beginner blog writers?
    I’d genuinely appreciate it.

    Reply
  106. บาคาร่า

    I am extremely impressed with your writing skills as well as with the layout on your weblog.

    Is this a paid theme or did you modify it yourself? Either way keep up the nice quality
    writing, it’s rare to see a nice blog like this
    one today.

    Reply
  107. 일본야동

    Link exchange is nothing else however it is only
    placing the other person’s webpage link on your page at proper place and other person will also do same in favor of you.

    Reply
  108. cityofhonda.com

    I have learn a few good stuff here. Certainly worth bookmarking for revisiting.
    I surprise how much attempt you place to create this sort of wonderful informative website.

    Reply
  109. Online Slot

    I have been exploring for a bit for any high-quality articles or blog posts in this kind of area .

    Exploring in Yahoo I finally stumbled upon this website.
    Studying this information So i’m happy to show that I have a very excellent
    uncanny feeling I came upon exactly what I needed. I so much for sure will make
    certain to don?t disregard this site and provides it a look
    regularly.

    Reply
  110. airtahvie.com

    I do not even know how I ended up here, but I thought this post was good.
    I don’t know who you are but definitely you are going to
    a famous blogger if you are not already 😉 Cheers!

    Reply
  111. ajorco.com

    Excellent beat ! I wish to apprentice while
    you amend your site, how could i subscribe for a blog site?
    The account aided me a acceptable deal. I had been a little bit acquainted of this your
    broadcast provided bright clear idea

    Reply
  112. nobabbd.com

    When someone writes an post he/she keeps the thought of a user
    in his/her mind that how a user can be aware of it.
    Thus that’s why this post is great. Thanks!

    Reply
  113. UFA

    Wonderful blog! I found it while surfing around on Yahoo News.

    Do you have any tips on how to get listed in Yahoo News?

    I’ve been trying for a while but I never seem to get there!
    Cheers

    Also visit my web site – UFA

    Reply
  114. vreyro linomit

    Hey there, I think your website might be having browser compatibility issues. When I look at your blog in Opera, it looks fine but when opening in Internet Explorer, it has some overlapping. I just wanted to give you a quick heads up! Other then that, terrific blog!

    Reply
  115. fotograaf spijkenisse

    Does your site have a contact page? I’m having trouble locating it but,
    I’d like to send you an e-mail. I’ve got some creative ideas for your blog
    you might be interested in hearing. Either
    way, great site and I look forward to seeing it expand over time.

    Also visit my blog fotograaf spijkenisse

    Reply
  116. sex seyret

    Sanal ofis, bir ofise ihtiyaç duymayan sirket sahiplerinin faydalandigi bir uygulamadir. Yeni bir girisimde bulunmak isteyen kisilerin, islerini yasal bir biçimde yürütebilmeleri için sirket kurulumlarini gerçeklestirmeleri gerekir. Ancak sirket kurulumu yapilabilmesi için resmi olarak gösterilebilecek bir adrese ihtiyaç vardir. Sanal ofisler de bu noktada sirket sahibi olmak isteyenlere hem prestijli bir adres hem de ihtiyaçlari olacak pek çok hizmeti sagliyor.

    Reply
  117. IPTV Extreme

    I’m not sure exactly why but this blog is loading very slow for me.

    Is anyone else having this issue or is it a issue on my end?
    I’ll check back later and see if the problem still exists.

    Check out my blog post … IPTV Extreme

    Reply
  118. crm ejemplos

    Hi, I do think this is a great site. I stumbledupon it 😉
    I’m going to come back yet again since i have book marked it.
    Money and freedom is the best way to change, may
    you be rich and continue to help others.

    Also visit my page; crm ejemplos

    Reply
  119. karokasb.com

    I’m very happy to discover this page. I want to to thank you for your time just for this fantastic read!!
    I definitely savored every part of it and i also have
    you saved as a favorite to look at new stuff in your web
    site.

    Reply
  120. consultoria empresarial

    When I initially commented I seem to have clicked on the
    -Notify me when new comments are added- checkbox and from now on every time a comment is added
    I recieve four emails with the exact same comment. There has
    to be a means you are able to remove me from that service?
    Appreciate it!

    My blog post: consultoria empresarial

    Reply
  121. google my business

    Wonderful website you have here but I was curious if you knew of any forums that cover the same topics discussed here?
    I’d really like to be a part of community where I can get
    responses from other experienced individuals that share the same interest.
    If you have any recommendations, please let me know.
    Bless you!

    Look into my web blog google my business

    Reply
  122. dafellowship.com

    I know this if off topic but I’m looking into starting my own blog and was
    curious what all is required to get setup? I’m assuming having
    a blog like yours would cost a pretty penny? I’m not very internet smart so
    I’m not 100% positive. Any tips or advice would be greatly appreciated.
    Many thanks

    Reply
  123. idnluck.com

    Good day! I could have sworn I’ve been to this website before but after browsing through some of the post I realized it’s new
    to me. Anyways, I’m definitely delighted I found it and I’ll be
    book-marking and checking back often!

    Reply
  124. jackson131.soufianegame.com/57.html

    Definitely believe that which you stated. Your favorite justification seemed to be on the internet
    the easiest thing to be aware of. I say to you, I certainly get
    irked while people think about worries that they
    plainly don’t know about. You managed to hit the nail upon the top and also defined out the whole thing without having side-effects
    , people can take a signal. Will probably be back to get more.
    Thanks

    Reply
  125. transfer programs to new computer

    I have been exploring for a little for any high quality articles or blog posts on this kind of house .

    Exploring in Yahoo I ultimately stumbled upon this site.

    Reading this information So i’m glad to express that I have a very good uncanny feeling I came upon exactly what I needed.
    I such a lot no doubt will make certain transfer programs to new computer do not disregard this web site and provides
    it a glance regularly.

    Reply
  126. 0wdXRGaxWo

    815747 488840You produced some decent points there. I looked online for your dilemma and located a lot of people will go together with with the internet site. 386286

    Reply
  127. Felicia

    What’s up to all, the contents existing at this website
    are actually awesome for people experience, well, keep
    up the good work fellows.

    Reply
  128. elvnime.com

    Howdy! This is my 1st comment here so I just wanted to give a quick shout
    out and tell you I genuinely enjoy reading your blog posts.
    Can you recommend any other blogs/websites/forums that cover the same topics?
    Appreciate it!

    Reply
  129. 토토사이트

    Excellent post. Keep posting such kind of info on your site.
    Im really impressed by your blog.
    Hi there, You have performed a great job. I’ll certainly digg it and in my view
    suggest to my friends. I am sure they’ll be benefited from this website.

    Take a look at my web blog: 토토사이트

    Reply
  130. collagen

    Hmm it appears like your site ate my first comment (it was
    extremely long) so I guess I’ll just sum it up what I wrote and say, I’m thoroughly enjoying your blog.
    I as well am an aspiring blog writer but I’m still new to the whole thing.
    Do you have any tips for rookie blog writers? I’d really appreciate
    it.

    my site: collagen

    Reply
  131. validoomed.com

    Hi my family member! I want to say that this post is awesome, great written and come with approximately all important infos.
    I would like to look more posts like this .

    Reply
  132. 먹튀

    Nice weblog right here! Also your web site so much up very fast!
    What host are you the usage of? Can I get your
    affiliate link in your host? I desire my website loaded up as quickly as yours
    lol

    Also visit my web-site … 먹튀

    Reply
  133. 먹튀검증

    I was wondering if you ever considered changing
    the page layout of your blog? Its very well written; I love what youve got to say.

    But maybe you could a little more in the way of content so
    people could connect with it better. Youve got an awful
    lot of text for only having one or 2 images. Maybe you could space it out better?

    Also visit my site … 먹튀검증

    Reply
  134. prikwebresources.com

    After checking out a handful of the articles on your website, I really like your way of blogging.
    I added it to my bookmark website list and will be checking
    back soon. Take a look at my website as well and let me
    know how you feel.

    Reply
  135. chooppa.com

    Hello there, You have done a great job. I’ll definitely digg it and personally suggest to my friends.
    I am sure they will be benefited from this site.

    Reply
  136. site

    Attractive section of content. I just stumbled upon your weblog and in accession capital to assert
    that I get actually enjoted account your blog posts.
    Anyway I’ll bee subscribing to your augment and even I achievement you achess consistently fast.

    site

    Reply
  137. IPTV Panel

    When I originally left a comment I appear to have clicked on the -Notify me when new comments are
    added- checkbox and now every time a comment is added I recieve four
    emails with the same comment. There has to be a means you can remove me from that service?
    Thank you!

    Feel free to surf to my website :: IPTV Panel

    Reply
  138. IPTV Extreme

    I don’t know whether it’s just me or if everybody else
    encountering issues with your blog. It appears as if some of the written text
    within your content are running off the screen. Can somebody else please provide feedback and let me know if this is happening to them as well?
    This may be a issue with my browser because I’ve had this happen before.
    Many thanks

    My site – IPTV Extreme

    Reply
  139. IPTV Pro

    I am extremely impressed with your writing skills and also with the
    layout on your blog. Is this a paid theme or did you customize it yourself?
    Either way keep up the nice quality writing, it’s rare
    to see a nice blog like this one today.

    my web blog … IPTV Pro

    Reply
  140. 메이저사이트

    Does your blog have a contact page? I’m
    having trouble locating it but, I’d like to send you
    an e-mail. I’ve got some suggestions for your blog you might be interested in hearing.
    Either way, great website and I look forward to seeing it grow over time.

    My homepage – 메이저사이트

    Reply
  141. computer store

    An impressive share! I have just forwarded this onto a colleague who had been conducting a little research on this.
    And he in fact bought me breakfast simply because I stumbled
    upon it for him… lol. So let me reword this….
    Thanks for the meal!! But yeah, thanx for spending the time to talk about this issue here
    on your web page.

    Feel free to visit my webpage :: computer store

    Reply
  142. ruay

    Hello, i think that i saw you visited my website so i came to “return the
    favor”.I am attempting to find things to enhance my site!I suppose its ok to
    use some of your ideas!!

    Reply
  143. subway delivery near me

    Undeniably believe that which you said. Your favorite justification appeared
    to be on the web the easiest thing to be
    aware of. I say to you, I definitely get irked while people
    think about worries that they plainly don’t know about.

    You managed to hit the nail upon the top and also defined out the whole thing without having side-effects , people could
    take a signal. Will likely be back to get more.
    Thanks

    Feel free to surf to my homepage: subway delivery near me

    Reply
  144. หวยลาว

    Heya i’m for the primary time here. I found this board and I in finding It truly useful
    & it helped me out much. I am hoping to give something again and aid
    others such as you helped me.

    Reply
  145. bánh tráng nướng hàng tre

    Hi there would you mind stating which blog platform you’re using?

    I’m planning to start my own blog in the near future but I’m having a hard time deciding between BlogEngine/Wordpress/B2evolution and Drupal.
    The reason I ask is because your design and
    style seems different then most blogs and I’m looking for something completely unique.
    P.S My apologies for getting off-topic but I
    had to ask!

    Here is my homepage; bánh tráng nướng hàng tre

    Reply
  146. fc2

    It is perfect time to make some plans for the future and it’s time to be happy.

    I’ve read this post and if I could I want to suggest you some interesting things or suggestions.
    Maybe you can write next articles referring to this article.
    I desire to read more things about it!

    Reply
  147. anderson732.mahisaramotaf.com/baccarat-/

    I am really enjoying the theme/design of your
    web site. Do you ever run into any browser compatibility issues?
    A handful of my blog audience have complained about my website
    not working correctly in Explorer but looks great in Chrome.
    Do you have any recommendations to help fix this issue?

    Reply
  148. nuocwachi.com

    I like the valuable information you provide in your articles.
    I will bookmark your weblog and check again here regularly.

    I’m quite sure I’ll learn lots of new stuff right here! Good luck for the next!

    Reply
  149. cook847.trendayo.com/p/1

    Simply desire to say your article is as astonishing. The clarity in your publish is simply
    spectacular and i could think you’re an expert in this subject.
    Well with your permission allow me to clutch your RSS feed
    to stay updated with imminent post. Thanks 1,000,000 and please carry on the
    gratifying work.

    Reply
  150. hughes949.patinetando.com/exceptional-article--the-reality-to-slot-machines-that-only----/

    Howdy I am so happy I found your website, I really found you by
    mistake, while I was looking on Digg for something else, Nonetheless
    I am here now and would just like to say thanks for a fantastic post and a all
    round exciting blog (I also love the theme/design), I don’t have time to
    look over it all at the moment but I have saved
    it and also included your RSS feeds, so when I have time
    I will be back to read a great deal more, Please do keep
    up the fantastic work.

    Reply
  151. 펀초

    I seriously love your site.. Pleasant colors & theme.
    Did you make this site yourself? Please reply back as I’m looking to create m

    펀초
    y own personal blog and would like to
    learn where you got this from or just what the theme is called.

    Cheers!

    Reply
  152. wood252.jojobet128.com/p/1

    hey there and thank you for your info – I’ve definitely
    picked up something new from right here. I did however expertise some technical points using this web site, as I experienced to reload the web site
    lots of times previous to I could get it to load properly.
    I had been wondering if your hosting is OK? Not that I am complaining, but slow
    loading instances times will very frequently affect your placement in google and could
    damage your quality score if advertising and
    marketing with Adwords. Anyway I am adding this RSS to my e-mail and can look out for much more of your respective interesting
    content. Make sure you update this again soon.

    Reply
  153. rebeccadthomas.com

    Hi there, I found your blog by the use of Google while
    searching for a similar topic, your website got here up, it appears to be like good.
    I have bookmarked it in my google bookmarks.

    Hello there, just turned into alert to your blog via Google,
    and located that it is truly informative. I am gonna watch
    out for brussels. I will appreciate in case you continue this in future.
    A lot of people shall be benefited out of your writing.
    Cheers!

    Reply
  154. adams671.masalehkar.com/2020/12/this-is-of-blackjack-in-your-home.html

    Howdy! I know this is kinda off topic however I’d figured I’d ask.

    Would you be interested in trading links or maybe guest writing a blog article
    or vice-versa? My blog addresses a lot of the same topics as yours and I think
    we could greatly benefit from each other.
    If you happen to be interested feel free to shoot me an email.

    I look forward to hearing from you! Great blog by the way!

    Reply
  155. istanbuldavetiyeler.com

    I am really impressed with your writing skills as well as with the layout
    on your blog. Is this a paid theme or did you modify it yourself?
    Either way keep up the nice quality writing, it’s rare to
    see a great blog like this one nowadays.

    Reply
  156. skaibiz.com

    First off I want to say wonderful blog! I had a quick question in which I’d like to ask if you
    don’t mind. I was curious to know how you center yourself and clear your
    thoughts prior to writing. I’ve had difficulty clearing my mind in getting my thoughts out there.
    I do take pleasure in writing however it just seems like the first
    10 to 15 minutes tend to be lost simply just trying to figure out how to begin. Any ideas or tips?
    Kudos!

    Reply
  157. mitchell457.xdatechs.com/p/1

    Nice post. I was checking continuously this blog and
    I am impressed! Extremely useful info specifically the last part 🙂 I
    care for such information much. I was looking for this
    certain info for a very long time. Thank you and best of luck.

    Reply
  158. idhayaengg.com

    It’s a shame you don’t have a donate button! I’d definitely donate to
    this brilliant blog! I guess for now i’ll settle for bookmarking and
    adding your RSS feed to my Google account. I look forward
    to new updates and will talk about this site with my Facebook group.
    Chat soon!

    Reply
  159. medcuri.com

    Howdy! This is my first visit to your blog!
    We are a group of volunteers and starting a new initiative in a community in the same
    niche. Your blog provided us beneficial information to
    work on. You have done a marvellous job!

    Reply
  160. morgan567.upolf.com/2020/12/blackjack-/

    Howdy I am so delighted I found your webpage, I really
    found you by accident, while I was researching on Digg for
    something else, Nonetheless I am here now and would just like
    to say many thanks for a remarkable post and a all round
    thrilling blog (I also love the theme/design), I don’t have time to look
    over it all at the minute but I have saved it and also added in your RSS feeds,
    so when I have time I will be back to read more, Please do keep
    up the fantastic work.

    Reply
  161. moore886.acctum.com/archives/1

    Hi there, I believe your site could possibly be having browser compatibility problems.
    Whenever I look at your site in Safari, it looks fine but when opening in I.E.,
    it has some overlapping issues. I just wanted to provide
    you with a quick heads up! Apart from that, great site!

    Reply
  162. thammyanbinh.com

    I am not sure where you’re getting your info, but great topic.
    I needs to spend some time learning much more or understanding more.
    Thanks for magnificent info I was looking for this info for
    my mission.

    Reply
  163. 카지노사이트

    Hey would you mind sharing which blog platform you’re working with?
    I’m planning to start my own blog in the near future but I’m having a tough time choosing between BlogEngine/Wordpress/B2evolution and Drupal.
    The reason I ask is because your design seems different then most blogs and
    I’m looking for something completely unique. P.S My apologies for being off-topic but I had to ask!

    Reply
  164. surgical mask

    Sweet blog! I found it while searching on Yahoo
    News. Do you have any suggestions on how to get listed in Yahoo News?
    I’ve been trying for a while but I never seem to get there!
    Thanks

    Feel free to surf to my web page; surgical mask

    Reply
  165. silk pillowcase

    I do not know if it’s just me or if everyone
    else encountering issues with your website.

    It appears as though some of the text within your posts are running off the screen. Can someone else please provide
    feedback and let me know if this is happening to them too?
    This could be a issue with my browser because I’ve had
    this happen previously. Thank you

    my web-site :: silk pillowcase

    Reply
  166. surgical mask

    Hi there, I found your website by the use of Google at the same time as looking for a comparable
    matter, your site got here up, it appears to be like good.
    I have bookmarked it in my google bookmarks.

    Hello there, simply was aware of your weblog through Google,
    and found that it is really informative. I’m gonna watch
    out for brussels. I’ll appreciate in case you continue this
    in future. A lot of other folks might be benefited out of your writing.
    Cheers!

    my web-site surgical mask

    Reply
  167. cooper550.techcolz.com/2020/12/baccarat-----/

    Hey! This is kind of off topic but I need some help from an established blog.
    Is it tough to set up your own blog? I’m not very
    techincal but I can figure things out pretty quick. I’m thinking about setting up my own but I’m
    not sure where to begin. Do you have any ideas or suggestions?
    Thanks

    Reply
  168. green205.seoblogify.com/p/1

    I have been surfing online more than 4 hours today, yet I never found any interesting
    article like yours. It’s pretty worth enough for me. Personally, if all webmasters and bloggers made
    good content as you did, the net will be much more useful than ever before.

    Reply
  169. forex

    Link exchange is nothing else but it is only
    placing the other person’s blog link on your page at
    proper place and other person will also do similar for you.

    Reply
  170. realestateexampreps.com

    I’m not sure where you are getting your information,
    but good topic. I needs to spend some time studying more
    or working out more. Thanks for magnificent info I used to be searching
    for this information for my mission.

    Reply
  171. brown485.diyarbakirnakliyatci.com/1.html

    It’s a shame you don’t have a donate button! I’d definitely donate to this superb blog!
    I guess for now i’ll settle for book-marking and adding your RSS feed
    to my Google account. I look forward to new updates and will share this site with my
    Facebook group. Talk soon!

    Reply
  172. anderson298.defibtechushaarmour.com/ea-gay-sports.html

    Can I simply just say what a comfort to uncover somebody that truly understands what they’re discussing on the web.
    You definitely know how to bring an issue to light and
    make it important. More and more people really need to look at this and understand
    this side of the story. I was surprised you’re
    not more popular given that you most certainly
    possess the gift.

    Reply
  173. n-vier.com

    My brother recommended I might like this website.
    He was entirely right. This post actually made my day. You can not imagine just how much time I had spent
    for this information! Thanks!

    Reply
  174. Fancy Disposable Plastic Bowls

    Good day! I know this is kinda off topic but I’d figured I’d ask.

    Would you be interested in exchanging links or maybe guest authoring a blog post or vice-versa?
    My website goes over a lot of the same topics as
    yours and I think we could greatly benefit from each other.
    If you might be interested feel free to shoot me an email.
    I look forward to hearing from you! Wonderful blog
    by the way!

    Also visit my blog; Fancy Disposable Plastic Bowls

    Reply
  175. Clear Plastic salad Bowls

    Hello would you mind letting me know which web host you’re
    utilizing? I’ve loaded your blog in 3 completely different internet browsers and I must say this blog loads a lot quicker then most.
    Can you recommend a good web hosting provider at a fair price?

    Thanks, I appreciate it!

    Stop by my webpage – Clear Plastic salad Bowls

    Reply
  176. Plastic Dishes

    Hey there, I think your site might be having browser compatibility issues.
    When I look at your blog in Firefox, it looks fine but when opening in Internet Explorer, it has some overlapping.
    I just wanted to give you a quick heads up!
    Other then that, amazing blog!

    Also visit my blog post – Plastic Dishes

    Reply
  177. Party Supplies

    Hey I know this is off topic but I was wondering if you knew of any widgets I could add to my blog that automatically tweet my newest twitter updates.
    I’ve been looking for a plug-in like this for quite some time and was hoping maybe
    you would have some experience with something like this.

    Please let me know if you run into anything.
    I truly enjoy reading your blog and I look forward to
    your new updates.

    My web site; Party Supplies

    Reply
  178. Benjamin

    My family members always say that I am killing my time here at net, however I know I am getting experience daily by reading thes nice posts.

    Reply
  179. white530.codebuket.xyz/---sports.html

    You’re so interesting! I do not believe I have
    read through anything like that before. So good to discover somebody with genuine thoughts on this topic.
    Really.. thanks for starting this up. This website is one
    thing that is required on the web, someone with a little originality!

    Reply
  180. bureauveritasbrazil.com

    Its like you read my mind! You appear to know so much about this, like you wrote
    the book in it or something. I think that you could do with a few pics to drive the message
    home a little bit, but instead of that, this is magnificent blog.
    A great read. I’ll definitely be back.

    Reply
  181. tcdress.com

    I got this web page from my pal who informed me on the
    topic of this web page and now this time I am visiting this web page and reading very informative content at
    this time.

    Reply
  182. Fresh Coffee

    I love your blog.. very nice colors & theme. Did you create this website yourself or did you hire someone to do it for you?
    Plz reply as I’m looking to construct my own blog and would like to find
    out where u got this from. cheers

    My web blog: Fresh Coffee

    Reply
  183. kgslearning.com

    It’s really a great and helpful piece of info. I’m happy that you just shared this useful
    information with us. Please keep us up to date like this.
    Thanks for sharing.

    Reply
  184. hill356.bilalkocabay.com/2020/12/3--slot-machines----/

    Hmm it appears like your website ate my first comment (it was extremely long) so I guess I’ll just sum it up what I submitted and say, I’m thoroughly enjoying
    your blog. I too am an aspiring blog blogger but I’m still new to everything.
    Do you have any recommendations for beginner blog writers?
    I’d genuinely appreciate it.

    Reply
  185. scott957.elisebent.com/2020/12/slot-machines--.html

    Woah! I’m really enjoying the template/theme
    of this site. It’s simple, yet effective. A lot of times it’s very difficult to get
    that “perfect balance” between superb usability and visual appearance.
    I must say that you’ve done a excellent job with this.
    In addition, the blog loads extremely fast for me on Firefox.
    Superb Blog!

    Reply
  186. williams318.deeprahost.com/sports-/

    Greetings from Ohio! I’m bored to tears at work so I decided
    to browse your site on my iphone during lunch break. I
    enjoy the info you provide here and can’t wait to take a look when I get home.
    I’m shocked at how fast your blog loaded
    on my cell phone .. I’m not even using WIFI, just 3G ..
    Anyhow, fantastic site!

    Reply
  187. hill1015.makecareerhere.com/1.html

    My spouse and I absolutely love your blog and find nearly all of your post’s
    to be exactly I’m looking for. can you offer guest writers to write content
    in your case? I wouldn’t mind publishing a post or elaborating on many of
    the subjects you write regarding here. Again, awesome website!

    Reply
  188. khanandesaz.com

    Hi, i think that i saw you visited my web site so i came to
    “return the favor”.I am trying to find things to enhance my site!I suppose its
    ok to use some of your ideas!!

    Reply
  189. guneslertarims.com

    Hello, i think that i saw you visited my web site so
    i came to “return the favor”.I’m attempting to find things to enhance my website!I suppose its ok to use a few
    of your ideas!!

    Reply
  190. 1xbet игровые автоматы

    Салют,
    Друзья.

    В данный момент я бы хотел рассказать немного про xbet казино.

    Я думаю Вы искали именно про самые лучшие слоты 1xbet?!
    Значит эта наиболее актуальная информация про игровые автоматы 1xbet будет для вас наиболее полезной.

    Мы предлагаем больше информации про
    самые лучшие слоты 1xbet и также
    про казино 1хбет и про 1xbet с игровыми автоматами.

    На нашем сайте больше про 1xbet с игровыми автоматами, также информацию про лучшие слоты на 1xbet и про дающие слоты 1xbet.

    Узнай больше про 1xbet игровые автоматы или по ссылке
    http://1xbet-online.com/1xbet-kazino/

    Удачного Дня

    Reply
  191. martin930.grantstoneboots.com/baccarat-/

    I know this if off topic but I’m looking into starting my own blog
    and was wondering what all is required to get set up?
    I’m assuming having a blog like yours would cost
    a pretty penny? I’m not very web savvy so I’m not 100% certain. Any tips or advice would be
    greatly appreciated. Kudos

    Reply
  192. green746.balikesiruzmanemlak.com/p/1

    obviously like your web-site however you need to take a look at the spelling
    on several of your posts. A number of them are rife with spelling
    issues and I to find it very bothersome to tell the reality on the other hand I’ll definitely come again again.

    Reply
  193. darskhososi.com

    I believe that is among the such a lot important information for me.
    And i am satisfied reading your article. But should
    observation on few normal things, The web site style is
    wonderful, the articles is in point of fact excellent : D.
    Excellent activity, cheers

    Reply
  194. drsegoviano.com

    Howdy! I could have sworn I’ve been to this blog
    before but after reading through some of the post I realized
    it’s new to me. Nonetheless, I’m definitely delighted I found it and I’ll be book-marking
    and checking back frequently!

    Reply