[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 4.14.3 Socket Animation

When you have an animated actor you often want that actor to hold something in its hands. Or put a helmet on its head. For this purpose Crystal Space has the concept of sockets. Basically a socket is a triangle of the mesh on which you can attach other meshes. So when the triangle moves (because the model animates) the other mesh (like a weapon) will move with it. At this moment both 3D sprites (see section Sprite3D Mesh Object, and Cal3D sprites (see section SpriteCal3D Mesh Object) support this feature.

#### Defining the Socket

To define the socket you can specify it in the mesh factory file of the model. For Cal3D models this happens with something like this:

    <meshfact name="model">
      ...
      <params>
        ...
        <socket name="lefthand" tri="3" mesh="0" submesh="1" />
        <socket name="righthand" tri="5" mesh="0" submesh="2" />
      </params>
    </meshfact>

Basically you have to find out the mesh, submesh, and triangle that specifies the place where you want to attach things. In the example above we created two sockets, one for the left hand and one for the right hand.

For Spr3D models you have to do it like this:

    <meshfact name="model">
      ...
      <params>
        ...
        <socket name="lefthand" tri="3" />
        <socket name="righthand" tri="5" />
      </params>
    </meshfact>

So it is the same but Spr3D doesn't have the concept of meshes and submeshes.

#### Attaching a Mesh to a Socket

With this function you can attach a mesh to a socket for a Cal3D model:

    bool AttachMesh (iMeshWrapper* actorMesh, const char* socketName,
    	const char* objectFactoryName)
    {
      csRef<iSpriteCal3DState> cal3dstate = scfQueryInterface<iSpriteCal3DState> (
      	actorMesh->GetMeshObject ());
      if (!cal3dstate) return false;
      iSpriteCal3DSocket* socket = cal3dstate->FindSocket (socketName);
      if (!socket) return false;
      iMeshFactoryWrapper* objectFactory = engine->GetMeshFactories ()
      	->FindByName (objectFactoryName);
      if (!objectFactory) return false;
      csRef<iMeshWrapper> object = engine->CreateMeshWrapper (objectFactory,
      	objectFactoryName);
      actorMesh->GetChildren ()->Add (object);
      socket->SetMeshWrapper (object);
      // Set a relative transform to correct the orientation of the object
      // relative to the socket orientation.
      csTransform trans = ...;
      socket->SetTransform (trans);
      return true;
    }

For Spr3D it is exactly the same except that you have to use `iSpriteSocket` instead of `iSpriteCal3DSocket` and you can't currently change the relative transform.

#### Detaching a Mesh from a Socket

To remove a mesh from a socket you can do this:

    bool DetachMesh (iMeshWrapper* actorMesh, const char* socketName)
    {
      csRef<iSpriteCal3DState> cal3dstate = scfQueryInterface<iSpriteCal3DState> (
      	actorMesh->GetMeshObject ());
      if (!cal3dstate) return false;
      iSpriteCal3DSocket* socket = cal3dstate->FindSocket (socketName);
      if (!socket) return false;
      iMeshWrapper* object = socket->GetMeshWrapper ();
      if (!object) return false;
      actorMesh->GetChildren ()->Remove (object);
      socket->SetMeshWrapper (0);
      engine->RemoveObject (object);
      return true;
    }

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ]

This document was generated using texi2html 1.76.