Virtools Tutorials, Tips and Tricks

Here is one of multiple possible approaches to develop and provide components as part of a team. It works without selection sets and therefore is pre Virtools 4.0 compatible. We often used this one! (Today you may use selection sets which much more powerful and are maybe a result of this suggestion

There are two major mechanisms that this approach is based on

  • Level and therefore level scripts are not saved into NMOs
  • Parameter shortcuts can be saved without it's source and are remapped by name and type when loaded

Handling differs a bit depending on how much elements you need in your component-development-cmo from the bigger context. If the complete content of your CMO needs to be provided and doesn't clash with existent elements and you only need access to global parameters (thus sources for parameter shortcuts), then you import or recreate them on a level script. Now if you want to export all your content except the level scripts you do the following:

  • go to the level manager
  • select global
  • right-click and select "select children" from the context menu
  • now open another category from the children of global. For example 3D Objects
  • now right-click on the category you just opened and click on "select children"

You will now see that all the content of your level is selected. Now right-click on one item and choose "save as". Everything get saved except the level scripts where your test-framework for your component and the shared global parameter sources are.

If you don't want to save everything i.e. because you have imported stuff that you need for development but it's not part of the component, then script the save-logic i.e in a level script and activate it via a boolean parameter ("saveMode") or a key. To specify the elements to save you can use

  • groups
  • arrays
  • selection sets from the 3dLayout (limited to 3d entities)
  • collections (ObjectArrays)

 (Note: As mentioned this is for pre Dev 4.0 CMOs. With 4.0 there are the Selection Sets doing this for you.)

The way you import it, is another story and depends on project size and awaited component update frequency

I have a case where I procedurally create content in 3ds max. Using the quite new feature "RealWorld Scale" UV coordinates I also get usable UV generated. But when I imported the geometries into Virtools, the UVs had an offset of 0.5. I saw that if I turn off the Real World Scale, in 3ds max, I lost that offset. I also tried the new Dev4 Collada import but it seems to totally ignore tiling and offset values. So, here are the code snippets for a quick Max2Virtools.dle source code Mod, enabling RealWorldScale support. I only tested it for my case, so maybe it doesn't work for other cases – in that case it might serve as starting point.

In file export.cpp find the section that looks like this

    //– Apply tiling
    u=-uvgen.UOffset + 0.5f + ((u-0.5f)*uvgen.UScale);
    v=uvgen.VOffset + 0.5f + ((v-0.5f)*uvgen.VScale);

replace it with something like this

    //– Apply tiling
    // dbo 19.07.2007 – when using real world coords offset by 0.5
    // warning – just tested for my case – use this only as a starting point
    if (! uvgen.RealWorldCoords)
    {
        u=-uvgen.UOffset + 0.5f + ((u-0.5f)*uvgen.UScale);
        v=uvgen.VOffset + 0.5f + ((v-0.5f)*uvgen.VScale);
    }
    else
    {
        u=-uvgen.UOffset + ((u-0.5f)*uvgen.UScale);
        v=uvgen.VOffset  + ((v-0.5f)*uvgen.VScale);
    }

in that same file you have something like

    uvgen.AngleMap        = uvs->GetAng(0);
    uvgen.Cropping        = FALSE;
    uvgen.UCropOffset    = 0;
    uvgen.VCropOffset    = 0;
    uvgen.UCropScale    = 1.0f;
    uvgen.VCropScale    = 1.0f;

 append one line so it looks like this:

    uvgen.AngleMap        = uvs->GetAng(0);
    uvgen.Cropping        = FALSE;
    uvgen.UCropOffset    = 0;
    uvgen.VCropOffset    = 0;
    uvgen.UCropScale    = 1.0f;
    uvgen.VCropScale    = 1.0f;

    uvgen.RealWorldCoords = uvs->GetUseRealWorldScale();

In the file Max2Nemo.h replace this

struct TextureUVGen {
    BOOL TileU,TileV;
    BOOL MirrorU,MirrorV;
    BOOL Cropping;
    float UOffset,VOffset;
    float UScale,VScale;
    float AngleMap;
    float UCropOffset,VCropOffset;
    float UCropScale,VCropScale;
    TextureUVGen() {
        TileU = TileV = MirrorU = MirrorV = Cropping = FALSE;
        UOffset = VOffset = AngleMap = UCropOffset =VCropOffset = 0.0f;
        UScale = VScale = UCropScale = VCropScale                = 0.0f;
    }
};

with this

struct TextureUVGen {
    BOOL TileU,TileV;
    BOOL MirrorU,MirrorV;
    BOOL Cropping;
    BOOL RealWorldCoords;
    float UOffset,VOffset;
    float UScale,VScale;
    float AngleMap;
    float UCropOffset,VCropOffset;
    float UCropScale,VCropScale;
    TextureUVGen() {
        RealWorldCoords = TileU = TileV = MirrorU = MirrorV = Cropping = FALSE;
        UOffset = VOffset = AngleMap = UCropOffset =VCropOffset = 0.0f;
        UScale = VScale = UCropScale = VCropScale                = 0.0f;
    }
};

You are ready! Note this is for 3ds max8 and +
If you need the binary for 3ds max8, send me an eMail.

I was inspecting some VSL scripts when I recognized that one wasn't compiled. It didn't because of a compiler error of type "cannot convert  from 'enumXYZ' to 'enumABC'". What happened? Name clash! The F&E manager ini file imported F&E definitions from other projects (thus not used in this project). One of my older projects and this one are using the same keyword for one of the their Enums: "none". 'None' is really a often used keyword, just like "left", "right", "on", "enable" etc.

I don't know where else this .ini would be really useful, when the editor would provide buttons for exporting and importing definitions via separate .ini/.xml files. Maybe just add a resource category with it, so if a developer needs to share or reuse enums or flags, just let him import them via drag and drop.

This .ini file made more trouble in the past then benefits, especially as the definitions are saved into the CMO anyways. This is probably one of the side effects from the lack of a proper project-management functionality for DEV. In meanwhile, you maybe want to delete that ini file often and/or prefix your enum-names with the type name.

I added a new Dialog to my Interface plugin for Virtools Dev 3.5. It allows to quickly delete all attributes from one or several categories. The standard attribute manager moves the attributes if you delete the category but does not delete them.

New dialog in DomsInterfaceExtensions PlugIn

In 4.0 you now have the possibility to delete all unused attributes, but I think Matthew said, that it doesn't consider attributes used in VSL scripts – what might be tricky to support. I don't know if this was changed for Virtools Dev 4.0 SP2, but 3.5 users have now better control anyways.

Download the plugin for 3.5  

 Enjoy ! 

Cool

p.s. here is a little chat log from the IRC channel, maybe it helps if you are unsure how it works:

[15:47] LeDom: ok, it takes less than 20 seconds to free you from 470 attributes
[15:47] LeDom: just did a test with one of our projects at work
[15:48] LeDom: a) install DLL
 b) start dev 3.5
 c) load CMO
 d) open main menu -> Dom's -> "Delete Attributes by Category"
[15:49] Vsaiwrk: nice.. thats a lot faster >:)
[15:49] LeDom: e) hit the button "select all"
 f) click on the categories from your project to deselect them
[15:49] LeDom: g) hit the "->" button
[15:49] LeDom: h) click DELETE button i) close the dialog
[15:50] LeDom: k) go to the attribute manager j) if it still shows all the attributes, close it again and reopen it
[15:50] Vsaiwrk: have to close and reopen the attribute manager if you already had it open still
[15:50] LeDom: (yeah f5 doesn't work here)
[15:51] LeDom: l) open "-No Category-" tree/section
[15:51] LeDom: j) select all the attributes in that section using shift
[15:51] LeDom: l) hit "del" key
[15:51] LeDom: m) done, enjoy, relax be happy
[15:51] LeDom: 😉
[15:52] Vsaiwrk: deleting the category deletes the attributes in that category also here.. you're saying it should put them under no category?
[15:53] LeDom: ?
[15:53] LeDom: no, but you may have some there by default
[15:53] LeDom: it does kill them all but no category is no category and therefore not touched
[15:53] LeDom: by my dialog
[15:53] LeDom: maybe i need to add a button for this too
[15:53] Vsaiwrk: gotcha

Last week typeRice asked if somebody knows a way to hide all 2D frames at once. I remembered that there is a 2d root object and suggested to get it and hierarchical-hide it. It worked! He then found out that you need to restore the state with hide, not show.

I now added some commands to my HTMLView Virtools interface plug-in, that allows to hide, show, and hierarchical hide objects by name and type. This way you can create your own GUI i.e. for quickly hiding specific entities.

The beta-1 version of the plug-in was released the 1st July 2006 and since then downloaded 96 times which doesn't sound much. It was the second release that featured a new font-setup GUI for interactive font-settings tweaking. Based on the feedback, Posy seems the most interesting element of the collection. Personally, I also use the time slider and the animation slider a lot. The HTMLView has a lot of potential but I only implemented a small subset of the ideas I have. In 2006 I used it to manage a presentation with it. It was at the FMX where my boss and I – together with our reseller – did a speech/demo/presentation about Virtools for game and shader development. I did a life demo of how shader development looks like when using Virtools DEV and then showed some shader examples from our projects and the online community. I was told that the people of the audience looked impressed. HTMLView helped me to quickly load the CMOs I wanted to demo and the HTML page also contained shader code fragments that i could copy/paste to make sure that the demonstration run smooth and quickly. I think Virtools teachers and trainers should take another closer look at this, if they don't use it yet. It might be a good support.

:)

Download of the new version for Virtools DEV 3.5

Please provide me with feedback, thanks. 

If you are using Virtools 4.0, I am sorry to say that there is currently no plug-in available for that version. I hope Virtools finds an acceptable solution in regards to the new EULA and web-publishing for every side, soon. Maintenance was paid for upgrades, but the EULA change was a heavy downgrade.

Let me end with some pictures from the FMX 06

Me doing a demo of shader development with Virtools Mr. R. Wagner doing a demo of a game prototype Virtools DEV for game prototyping demo by Mr. R. Wagner One of many test rigs to record stereoscopic videos Modelling with haptic feedbacl

In case you want your exporter to be able to assign attributes to exported entities based on some custom data in your DCC tool, then beware of the SetAttribute method of the Ge2Virtools. In case that you assign an attribute that has no parameter, the Ge2Virtools lib will create you an attribute with a parameter of a type from the font system anyways.

I send that issue to Virtools support over a week ago, but got no answer. I guess they are in holdiays or again they don't have enough people to handle all the input and wait time is 2 weeks (we had that quite often in the past).

So what you got to do is, reimplement the SetAttribute method and check if the type string is empty. If so, use

att = am->RegisterNewAttributeType(attributeName, CKGUID(0,0)); 

Getting a list of all portals is a bit more complicated than one might think at first as it's not a class. A portal is a 3D Entity with special flags. So here is the Run VSL code. Note that scene is a pIn of type Scene and portals is a pOut of type ObjectArray. I am also using feranti's for-loop style

Wink

void main()
{
    ObjectArray ents;
    bc.FillObjectArrayByType(ents, CKCID_3DENTITY, false, scene);
    int count = ents.Size();
    Entity3D ent = NULL;
    portals.Clear();
    for(int i=-1; ++i<count;)
    {
        ent = Entity3D.Cast(ents[i]);
        if( and(ent.GetFlags(), CK_3DENTITY_PORTAL) )
        {
            portals.PushBack(ents[i]);
        }
    }
}

I am serious about this. CMOs can get corrupt – usually if something with the VSL manager went wrong. In most cases you can trash your CMO. Therefoe use

CTRL + SHIFT + S

regulary. You are using a versioning control system i.e. like subversion? No problem: checkout your file, then always save into new files. Before the commit copy all the versions but the last one into an "OLD" (or however you want to name it) folder. Then take off the version numbers and commit your CMO. This is how I do it – you always have like 10 files between in each commit as backup in case you come back next morning discovering something you didn't saw the night before.

So the golden rule is: don't overwrite a CMO i.e. using CTRL+S – always save into a new CMO.

Just a little hint: the XStringTokenizer class is also available in VSL. It's really useful.

// VSL BB code
void main()
{
    // normally fill that via pIns
    String text = "hallo#this#is#a#tokenizer#test#endOfMessage";    
    String delimiter = "#";

    // the tokenizer stuff
    StringTokenizer tokenizer(text.Str(), delimiter.Str());
    str token = NULL;
    while( (token= tokenizer.NextToken(token)) != NULL )
    {
       bc.OutputToConsole(token);
    }
}