Write a importer

From Virtools Wiki

Jump to: navigation, search


Contents

Write a Importer for Virtools 4.0 with Visual Studio .NET 2003

This article will discuss and show you howto to create a custom file importer plugin for Virtools 4.0. There can be difference in writing plugins to other versions of Virtools, so this article is only recommended for those who are using Virtools 4.0.

Also worth mentioning, that I use Visual Studio .NET 2003 during this article.

There are several different plugins you can create for Virtools, and this article will only show how to load a Model to Virtools (CKPLUGIN_MODEL_READER).

Create The Virtools Plugin

When creating a project for your plugin using Visual Studio, I recommend you use the Wizard app that ships with Virtools 4.0. This section I will show the common things to write in, when filling out the plugin information. But i will not show everything. Each subsection is a seperate function that you will find when working with a plugin project for Virtools.

What I have written down below, is functions that you need in your plugin class. The cpp file generated by the plugin wizard will not be dealt with here. The best way to truly understand howto make the plugin work when compiling in Visual Studio, is to look at the source code examples that is shipped with Virtools.

CKGetPluginInfo

This function is where you put information about your plugin. What information that needs to go where, is pretty straight forward. The function should have atleast the following information:

int Plugin = 0;
g_PluginInfo[Plugin].m_Author			= "Your name, or the company's name";
g_PluginInfo[Plugin].m_Description		= "Short description of the plugin";
g_PluginInfo[Plugin].m_Extension		= "The file extension that your plugin supports (x, obj, jpg...)";
g_PluginInfo[Plugin].m_Type			= CKPLUGIN_MODEL_READER;
g_PluginInfo[Plugin].m_Version			= 0x00000002;
g_PluginInfo[Plugin].m_InitInstanceFct	        = NULL;
g_PluginInfo[Plugin].m_GUID			= CKGUID(0x697c6058, 0x72f66491);
g_PluginInfo[Plugin].m_Summary			= "Short summary for your plugin";
return &g_PluginInfo[Index];

  • m_Type, is to show Virtools what kind of plugin this is.

'CKPLUGIN_MODEL_READER' in this case, tells Virtools that it is a file loader plugin, that only loads/reads the file extension. There are different options that you can choose. Please read further in the SDK documentation.

  • m_GUID, the CKGUID should have different memory variables for each plugin. You should use 'CKGuidGen.exe' application found in 'Utils' to generate a memory adress for you.

CKGetReader

This function should return a new instance of your plugin class

CKDataReader *CKGetReader(int index)
{
 // new CKReader()
 return new CKReader();
}

Load

Load function is a virtual function that you MUST use in order to make the plugin compile and work with Virtools. This function is the actual starting point of your plugin (File loader). From this function you will call on all functions that you need to run to get the job done.

The definition for the function looks like this:

virtual CKERROR Load(CKContext *pContext,CKSTRING FileName,CKObjectArray *pArray,CKDWORD LoadFlags,CKCharacter *pCharacter);

GetOptionsCount

This is another virtual function that you must define and declare in your class. But i havent used these functions at all. so you can leave them blank, if you do not have the need for it.

The definition for the function looks like this:

virtual int GetOptionsCount(void);

GetOptionDescription

This is another virtual function that you must define and declare in your class. But i havent used these functions at all. so you can leave them blank, if you do not have the need for it.

The definition for the function looks like this:

virtual CKSTRING GetOptionDescription(int i);

Import data into Virtools structs

Now when you have hopefully made the plugin to compile, you will need to load all information into Virtools.

Create Export2Virtools

Before doing anything else, you need to create a pointer to the Export help class in Virtools.

m_pVirtoolsExport = new Export2Virtools(pContext, FALSE);

The context pointer is found as a imparameter in the Load function (see above for more information)

Create VirtoolsTransitionMesh

When loading in all data into Virtools, you need to first store all the information temporarly in a class. The class is called 'VirtoolsTransitionMesh'. The only inparameter is the Export2Virtools pointer that you should have already.

VirtoolsTransitionMesh TransitionMesh(m_pVirtoolsExport);

Load Vertices

This function takes in one position point at the time and adds it to a Virtools list.

TransitionMesh::AddPosition(VxVector *pos)

You should loop through all the points you want to add to Virtools, and add them like above.

Load Faces

Loading faces to the Virtools file structure is just like loading vertices. But the function may look little trickier at first glance, since it doesnt really say how it wants the information, nor are there any information in the SDK documentation. Lets look at the function:

TransitionMesh::AddFace(int index1, int index2, int index3, CKMaterial *m);
TransitionMesh::AddFace(int *indices, int indexcount, CKMaterial *m);

The first one takes in three different indexes. Which means three points that makes the face itself. The second one takes in a int pointer instead of the three sepeare points as the first one. This simply means that instead of using ex. index[1], index[2], index[3] you just use index as a inparameter, and state that index contains 3 indices.

Both functions has a third option if this current face has a material. If you dont have a material or dont want to use one, just set NULL for the CKMaterial inparameter.

Load UV coordinates

Exporting texture coordinates are as simple as above functions. The function looks like this: TransitionMesh::AddUv(TempUV); The inparameter 'VxUV' is a variable with a .u and a .v variable. The UV coordinates that comes from the 3D application could be a vector or a float3 variable. If that is the case, just take the two first variables, and put the first one into .u and the second one into .v and you should be fine.

Now you have setup the UVs, but you need to setup the UV indices aswell. This can be most easily done when loading your faces to the Virtools file, but you can in theory load them whenever you want.

TransitionMesh::AddUVFace(int index1, int index2, int index3,int channel = 0);

This function sets up the UV faces for you. Basicly this function needs to know the face index. Remember that a face consists of three points to make a face. So each point in that face, is a index value that this function needs. So easiest is to do it like this:

int FaceIndex = 0;
for(int i = 0; i < NumberOfFaces; i++, FaceIndex += 3)
{
 // Add face function
 TransitionMesh::AddFace(pFaceArray, VertexCount, NULL);
 // Add UV face function
 TransitionMesh::AddUVFace(FaceIndex, FaceIndex + 1, FaceIndex + 2);
}

This pseudo code shows that you just add a ascending number to each point you have loaded in. And since the face has three points, you put in 1,2,3 and then jump three points, and next time you add 4,5,6 etc until you have loaded all your faces.

Load Material

What I do here, I add a empty Virtools material to the object. If you want to add one material to a object you just go through the following code:

// Create a material
CKMaterial *pMaterial = (CKMaterial *)CKContext::CreateObject(CKCID_MATERIAL, "Material");
// Set the material for the whole face
for(int i = 0; i < TransitionMesh->m_Faces.Size(); i++)
TransitionMesh::SetFaceMaterial(i, pMaterial);

This will apply one material for the whole face size (all faces). It is possible to add several materials to your Virtools file. All you need to do is let the Virtools material know which faces this specific material should use.

Load a Texture

Adding a texture to your object, you will need to attach it to your material. First you need to create a texture object:

CKTexture *pVirtoolsTexture = (CKTexture *)CKContext::CreateObject(CKCID_TEXTURE, TextureName);

This returns a texture pointer which we will use: pVirtoolsTexture->LoadImage(TextuePath); This function returns TRUE if successfull. If the function returns FALSE, there could be couple of reasons.

  • The filepath is incorrect. Check the address once more and make sure its valid
  • The filetype is not supported. Change to a supported filetype. Virtools only supports the basic ones (jpg, bmp, tga...). You can add your own filetype support by creating a dll file for that specific filetype

If the function was successfull, we have a texture saved into that texture pointer. So now it must be assigned to a material which will display the texture. If the texture is not assigned to a material, it will still exist in the file, just not used until assigned:

CKMaterial::SetTexture(pVirtoolsTexture);

Generate Virtoolsdata

After adding all the data you needed into the TransitionMesh, you will need to generate all the data so you can use it with virtools to create our object!

VirtoolsTransitionMesh::GenerateVirtoolsData()

The function actually creates an array for the vertices and the faces in Virtools. It will return TRUE if it was successfull. If false, that means that some of your input data (vertices, faces...) are either stored incorrectly or maybe invalid.

Add generated data to Virtools

Now when you have loaded all the needed data into Virtools, you need to add this data (or entity) so that Virtools can show it on screen, and enable so you can edit its variable and add different functionalities to it inside Virtools.

Create Mesh

First you need to create a mesh from all the data.

CKMesh *pMesh = m_Export2Virtools::AddMesh(VirtoolsTransitionMesh::TransitionMesh, char *MeshName);

The inparameter is the temp mesh structure that you have been working with, and a optional name for the mesh that you are creating. If successfull, this function will return a pointer to the created mesh.

Create CK3dEntity

In order to see the mesh in Virtools and be able to edit it realtime, you need to create a 3dEntity and then add the mesh to it.

CK3dEntity *p3DObjectEnt = (CK3dEntity *)m_Export2Virtools::Add3dObject(char *pObjName);
p3DObjectEnt->SetCurrentMesh(pMesh);

Add 3dEntity to Virtools level

Now everything is finished, except seeing the actual object in the 3D Layout. To do this, you need to get a pointer of the current level (3D layout) and add the object to its list.

CKLevel *pCurrentLevel = CKContext::GetCurrentLevel();
pCurrentLevel->AddObject(p3DObjectEnt);

First function you will get the pointer to the current level, and with that pointer you will take the 3dEntity and add it to the current scene's object list.

Now you should be able to see the object in the 3D Layout, and see it in the Level Manager. There is alot of more functions and flags that you can add to your object, in order to set the object as a character and much more. Please look in the documentation for more information.

Also see

Write_a_exporter - Write a custom Virtools *.nmo file exporter

Personal tools
The Swap-Meet