NIM v0.9

Just released version 0.9 of NIM. Almost feature complete. Just missing the configuration dialog.

Added environment variable editing:
vars

Added log window:
log

See on GitHub

Posted in Application | Tagged , | Leave a comment

QT lambda slots

I’ve toyed with QT connections trying to create anonymous function when connecting a slot to a signal. For instance, I am trying to do the following:

menu->addAction( QIcon("some_icon.png"), "Open", this, SLOT(OnOpenTriggered()) );

So far so good, but sometime I find it cumbersome to define all the slots. Create a declaration, a definition, etc…

I would like to declare the body right there! Here’s what I would like to do using std::function or a c++ lambda:

menu->addAction( QIcon("some_icon.png"), "Open", _Q, _Q->Call( [this](){
    // body here...
    this->showNormal(); // e.g.
} ) );

I’ve achieved that by creating a global object named _Q which is responsible to maintained the QT meta object information about all connection that needs to be called.

Here’s the header of the class in question:

class GlobalQTReceiver : public QObject
{
    Q_GADGET;
public:
 
    typedef std::function<void()> Func;
 
    GlobalQTReceiver();
 
    const char* Call(Func slotCallback);
 
protected:
 
    virtual const QMetaObject *metaObject() const override;
    virtual int qt_metacall(QMetaObject::Call, int, void **) override;
    virtual void* qt_metacast(const char *_clname) override;
 
protected Q_SLOTS:
 
    void func1();
 
private:
 
    struct FuncInfo {
        std::string name;
        std::string slotName;
        Func callback;
    };
 
    void FillMetaStructs();
 
    int mNextId;
    std::vector<FuncInfo> mFuncs;
    std::vector<uint> mMetaData;
    std::vector<char> mMetaString;
    QMetaObject mMetaObject;
};
 
extern QTUtils::Internal::GlobalQTReceiver* _Q;

And here’s the implementation:

 
GlobalQTReceiver::GlobalQTReceiver()
    : mNextId(0)
{
    FillMetaStructs();
}
 
const char* GlobalQTReceiver::Call( std::function<void()> slotCallback )
{
    std::stringstream ss;
    ss << "func" << mNextId++ << "()";
 
    FuncInfo fi;
    fi.name = ss.str();
    fi.slotName = "1"+fi.name;
    fi.callback = slotCallback;
 
    mFuncs.push_back( fi );
    FillMetaStructs();
 
    return mFuncs.back().slotName.c_str();
}
 
int GlobalQTReceiver::qt_metacall(QMetaObject::Call call, int id, void** args)
{
    Q_ASSERT( call == QMetaObject::InvokeMetaMethod );
 
    id = QObject::qt_metacall(call, id, args);
    if (id < 0)
        return id;
 
    Func slotCallback = mFuncs[id].callback;
    id -= mFuncs.size();
 
    slotCallback();
 
    return id;
}
 
void* GlobalQTReceiver::qt_metacast( const char *_clname )
{
    Q_ASSERT( !"not supported" );
    return nullptr;
}
 
const QMetaObject* GlobalQTReceiver::metaObject() const 
{
    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &mMetaObject;
}
 
void GlobalQTReceiver::FillMetaStructs()
{
    const char objectName[] = "QTUtils::Internal::GlobalQTReceiver";
    mMetaString.clear();
    mMetaString.insert(mMetaString.begin(), objectName, objectName+sizeof(objectName));
    mMetaString.push_back('\0');
 
      /* content:
      6,       // revision
        0,       // classname
        0,    0, // classinfo
        7,   14, // methods
        0,    0, // properties
        0,    0, // enums/sets
        0,    0, // constructors
        0,       // flags
        0,       // signalCount
        */
    mMetaData.clear();
    mMetaData.push_back( 6 ); // revision
    mMetaData.push_back( 0 ); // classname
    mMetaData.push_back( 0 ); mMetaData.push_back( 0 ); // classinfo
    mMetaData.push_back( mFuncs.size() ); mMetaData.push_back( 14 ); // methods
    mMetaData.push_back( 0 ); mMetaData.push_back( 0 ); // properties
    mMetaData.push_back( 0 ); mMetaData.push_back( 0 ); // enum/sets
    mMetaData.push_back( 0 ); mMetaData.push_back( 0 ); // constructors
    mMetaData.push_back( 0 ); // flags
    mMetaData.push_back( 0 ); // signalCount
 
    // slots: signature, parameters, type, tag, flags
    int offset = sizeof(objectName)+1;
    for (auto it = mFuncs.begin(), end = mFuncs.end(); it != end; ++it)
    {
        size_t funcNameLength = it->name.size();
        const char* funcName = it->name.c_str();
        mMetaString.insert(mMetaString.end(), funcName, funcName+funcNameLength);
        mMetaString.push_back('\0');
 
        mMetaData.push_back( offset ); // signature
        mMetaData.push_back( 36 ); // parameters
        mMetaData.push_back( 36 ); // type
        mMetaData.push_back( 36 ); // tag
        mMetaData.push_back( 0x09 ); // flags
        offset += it->name.size()+1;
    }
 
    // eod
    mMetaData.push_back( 0 ); 
 
    mMetaObject.d.superdata  = &QObject::staticMetaObject;
    mMetaObject.d.stringdata = &mMetaString[0];
    mMetaObject.d.data       = &mMetaData[0];
    mMetaObject.d.extradata  = nullptr;
}

The idea here is that we maintain the QMetaObject needed to dispatch the call, when qt_metacall is called, to the proper anonymous functions. The magic is done in FillMetaStructs() to maintain the meta object structure each time a new connection is made when Call(…) is called.

Posted in News | Tagged , | Leave a comment

node.js instance manager

node.js instance manager is a simple application that lets you manage the execution of multiple instance of node.js applications. You can play/stop many instances and monitor them using a simple UI that reside in the system tray. You can specify the port of all instances and many other process parameters.

Follow on GitHub (https://github.com/jschmidt42/nim)

Motivation

It is useful to have a single view on all your node instances that are running and being able to quickly restart them, etc.

Usage

main ui

  • You add a new node instance slot by pressing the Add button.
  • Then browse for a node.js startup script (same script you would start using node.exe on the command line).
  • If your node application is a server that needs a given port, enter it in the port field.
  • Finally press the Play button to start the node process. If it didn’t crashed at startup, the icon should pass to a stop button state.
    • Pressing the stop button will kill the node process
  • Repeat the process for other node instances.

Additional options

  • More node instance options…
    • more options
      • Open Browser: opens a browser view on http://localhost:port
      • Open Explorer: opens a file explorer view where the startup scripts is
      • Edit Env. Vars: edits environment variables that will be passed to the node process when started.
      • Log: opens a log window of the running node process.
      • Debug: adds the debug argument to the node process to be debugged
      • Delete: deletes the node instance slot
  • When you minimize the application it will be hidden from the application taskbar and a icon will be available in the system tray to re-open it.
    • system tray

Requirements

Posted in Application, Tool | Tagged , , | Leave a comment

Vicuna 2013.02

New Vicuna release (2013.02)

Download

Adding:

Updated PhysX to version 3.2.2

Minimal integration of Audiokinetic Wwise

Posted in News | Leave a comment

Vicuna 2012.12

Download here

Since winter classes of INF4715 is resuming soon. Here’s a new drop of Vicuna. There’s not that much changes. Mainly, I’ve integrated D3D9 as the animation system and updated PhysX to version 3. As for the animation system, I am working to support a full animation pipeline from 3dsmax to the game. Also I am working on a LUA integration.

Here’s a shot of the latest version in action:

ChangeLog:

Added a custom exception handler to dump the exception in the log file.
Added alpha testing to shadow maps
Added an animation Fixed applying bone transforms
Added event system Added component system
Added physic to barrel in the room
Added pivot support to the exporter
Added some production scripts
Added the ability to see which render nodes are in the frustum view
Adds logger
Adds new D3D9 model loader
Adds render state block support Removes some D3D9 dependencies in GameApp 
Adds Unicode support to logger
Building new interior scene
Creates VCNAnim project
Defines UNICODE in Release for VCNTests
Delete big 3rd party installer
Fixed camera cross product using proper left hand system
Fixed compilation error
Fixed mesh bounding sphere computation 
Fixed point light bounding sphere computation 
Fixed shading modes (use F3 to toggle modes)
Fixed skinning homogeneous coordinate (was causing unwanted scaling) 
Fixes compilation
Fixes fullscreen mode
Fixes includes
Fixes node deallocation
Fixes scaling of physic static mesh Tries another physic simulation loop 
Fixes some leaks
Makes VCNTests use Unicode
Many NRVO optimizations
Many optimizations
Merged littexture shader and effect (only one remaining)
Merged terrain shader and effect
Minor tweaks
Moved solutions files to Build/
Moves 3rdparty MessageBox library to the 3rdparty/ folder
Optimized matrix GetRotation
Optimized particle core by 20X
Reduced the size of VCNNode from 260 bytes to 184 bytes
Refactor precompiled headers Adds a performance graph to track performance results through revisions
Refactored shader/effect code for simplification (no more D3D9 dependencies other than in VCND3D9)
Refactored the animation system a bit Changed the terrain static mesh
Refactored Vector classes
Refactored view normal matrix usage Optimized VCNRenderNode size from 272 bytes to 208 bytes
Refactors Awesomium handles
Removed ambiguous matrix * vector operator
Removed file prefix VCN
Removed SSAO effect
Removes an unneeded copy of the Awesomium rendering buffer (save ~5 FPS)
Removes some D3D9 dependencies in GameApp
Renames AnimatedNode to AnimationController
Renames shaders Adds support for mesh skins
Reversed matrix multiplication order (i.e MVP = M * V * P)
Reverted the PhysX simulation loop, was causing issue in FINAL
Separated the shadowing effect of the terrain to a second configurable pass.
Updated sun directional shadow map region
Updates AntTweakBar to version 1.14
Updates Awesomium to 1.6.4 Adds a simple test to call javascript Adds Awesomium C++ object handles
Posted in Application, C++, News | Tagged | Leave a comment

Auto Debug Procedure

Have you ever need to debug an application but you couldn’t start it from the debugger. An example is a process that gets launched from another application. Lets say you have a Visual Studio solution which handles 2-3 executable projects. You start one with the debugger and you want to break in another process as soon as it starts.

I wrote a small macro for Visual Studio for which you can easily mark an executable projects as to Auto Debug when it gets executed. It used Microsoft jitdebugger registry entry to make this works.

First you need to import this macro into Visual Studio:

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics
Imports Microsoft.VisualStudio.VCProject
Imports Microsoft.VisualStudio.VCProjectEngine
 
Public Module Quickies
 
    Sub RegKeySave(ByVal i_RegKey As String, _
               ByVal i_Value As String, _
      Optional ByVal i_Type As String = "REG_SZ")
        Dim myWS As Object
 
        'access Windows scripting
        myWS = CreateObject("WScript.Shell")
        'write registry key
        myWS.RegWrite(i_RegKey, i_Value, i_Type)
 
    End Sub
 
    Function GetMiscDumpPane() As OutputWindowPane
 
        Dim ow As OutputWindow = DTE.Windows.Item(Constants.vsWindowKindOutput).Object
        Dim pane As OutputWindowPane
 
        Try
            pane = ow.OutputWindowPanes.Item("MyMacrosPane")
        Catch ex As Exception
            pane = ow.OutputWindowPanes.Add("MyMacrosPane")
        End Try
        Return pane
    End Function
 
    Sub SetAutoDebug(ByVal state As Boolean)
 
        Dim linkerOutput As String
        Dim itemName As String
        Dim projectName As String
        Dim project As EnvDTE.Project
 
        If DTE.ActiveSolutionProjects.Length <> 1 Then
            MsgBox("Select one project within the Solution Explorer, then re-run this macro.")
            Exit Sub
        End If
 
        Dim pane As OutputWindowPane = GetMiscDumpPane()
 
        project = DTE.ActiveSolutionProjects(0)
        itemName = project.FullName()
 
        ' Get linker option
        If project.Kind = vcContextGuids.vcContextGuidVCProject Then
            Dim vcProj As VCProject = project.Object
            Dim configs As IVCCollection = vcProj.Configurations
 
            projectName = vcProj.Name
 
            Dim cfg As VCConfiguration = configs.Item(1)
            If cfg Is Nothing Then
                pane.OutputString("Project " & vcProj.Name & " has no valid configuration" & vbCr)
                Exit Sub
            End If
 
            Dim tools As IVCCollection = cfg.Tools
            Dim linkerTool As VCLinkerTool = tools.Item("VCLinkerTool")
            If linkerTool Is Nothing Then
                pane.OutputString("Project " & vcProj.Name & " has no output" & vbCr)
                Exit Sub
            End If
 
            linkerOutput = linkerTool.OutputFile
            linkerOutput = linkerOutput.Substring(linkerOutput.IndexOf("$(OutDir)") + 9)
 
        End If
 
        If state = True Then
            ' On
            RegKeySave("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\" & linkerOutput & "\debugger", "vsjitdebugger.exe")
 
            pane.OutputString("Project " & linkerOutput & " => Auto debug ON" & vbCr)
        Else
            ' Off
            RegKeySave("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\" & linkerOutput & "\debugger", "")
 
            pane.OutputString("Project " & linkerOutput & " => Auto debug OFF" & vbCr)
        End If
 
    End Sub
 
    Sub SetAutoDebugOn()
        SetAutoDebug(True)
    End Sub
 
    Sub SetAutoDebugOff()
        SetAutoDebug(False)
    End Sub
 
End Module

Then follow the the steps above to install and use the macro:

  • Import the script Quickies.vb into VS2010 in the Macro Explorer

-         

  • Then open the customize tool in VS2010 by right clicking on the menu bar and select Customize…
  • Goto the Commands tab
  • Select ‘Toolbar’ radio button
  • Select in the list ‘Context Menus | Project and Solution Context Menus | Project’

-         

  • Then do Add Command…
  • Select the category ‘Macros’
  • Select the Macros called ‘Macros.MyMacros.Quickies.SetAutoDebugOn (repeat the same thing for SetAutoDebugOff)
  • Then you can change de label using the ‘Modify Selection’ button
  • Then finally, when you right click on a project you can set it to AutoDebug On or off like this:

         

  • One last thing, in the Macro Explorer under the Reference thing you need to add two references:

-         

Then when Auto Debug is on, then and the process gets launched of any manor, then you’ll get the option to debug it.

Posted in Tool | Tagged , | Leave a comment

INF4715: This year projects (2012)

Here’s a few videos on this year projects for the course I give at École Polytechnique de Montréal. All these games were made using C++ and Vicuna 2012, a small academic game engine that I maintain.

Rocketman

Toy Tank

Fantomas

Killforms

Rasinjas

Hotakadake

Posted in Gaming, News | Tagged , , | Leave a comment

C++11 Certified!

Yes I am now C++11 Certified!

This week we got a nice C++11 course giving by the guys from develop.com, over-viewing all the nice features of C++11.

My three favorite features are:
- auto

auto element = map_of_something.begin()->second;

- template alias

template<typename T>
using VCNHashTable = std::unordered_map<std::string, T>;
// ...
VCNHashTable<VCNEffect*> mEffects;

- and range for (not in VC10, but in VC11)

for( auto effect : mEffects )
{
  effect->RenderMesh(...);
}

See http://herbsutter.com/elements-of-modern-c-style/ for more info.

But why in hell, did they not add more nice features to std::string (trim(), split(), multiple favors of replace(), etc)? They just had too take a look at QString, String in C#. Bah! All other languages and popular libraries has nice string classes, but we are still with a low feature string class.

Posted in C++ | Tagged | Leave a comment

Check out Skyline and Space Madness at GDC 2012



Our game team at Autodesk worked really hard on Skyline and Space Madness for GDC and you can watch what we’ve made so far at http://area.autodesk.com/gdc2012.

Space Madness is a small game we made at Autodesk in a small period of time to showcase all our middlewares in one game.
http://area.autodesk.com/gdc2012/featured/fs-hypermadness?KeepThis=true&#ooid=s0NDBwMzpodiATMffzVuDvj39-l5Lq6R

Skyline is the product I directly work on, and its goal is to build a platform to use a high-end product such as Maya and easily edit your game content in real-time. At the moment, you can do animation authoring in real-time for your game with Skyline.

Posted in News | Tagged , , | Leave a comment

Named Return Value Optimization in Visual Studio 2010

I’ve made a few tests with VS2010 for Named Return Value optimization (NRVO). NRVO is a mechanism compilers use to pass the return capture of a statement and passes it as an argument to a function for you. For example, if you do

std::string MyStringFunc()
{
  return std::string( "The answer to life, the universe and everything is 42" );
}
std::string str = MyStringFunc();

Then the compiler guarantees that only one string will be created, the returned value, and that “str” will store that value. So what this means, is that you’ll save a copy. But one thing must be said about this, VS2010 only enable this optimisation with /O2 meaning that you won’t get the same behavior in Debug and Release builds, so caution must be taken.
In the following snippet, you’ll see that we don’t get the same result in Debug and Release:

#include <tchar.h>
#include <iostream>
#include <vector>
struct MyStruct
{
  // Default constructor
  MyStruct()
  {
    std::cout << "First" << std::endl;
    floats.resize( 1000000 );
    floats[0] = 76;
  }
  // Copy constructor
  MyStruct(const MyStruct& r) 
    : i(r.i)
    , j(r.j)
    , floats(r.floats)
  { 
    std::cout << "Copy" << std::endl; 
  }
  // Move constructor
  MyStruct(const MyStruct&& r) 
    : i(r.i)
    , j(r.j)
    , floats(std::move(r.floats))
  { 
    std::cout << "Move" << std::endl; 
  }
  // Destructor
  ~MyStruct()
  {
    std::cout << "Destruct" << std::endl; 
  }
  int i;
  int j;
  std::vector<float> floats;
};
 
const MyStruct GetVar()
{
  MyStruct s; // First
  s.i = 42;
  s.j = 24;
  return s; // Copy or Move or Nothing with /O2
}
 
int _tmain(int argc, _TCHAR* argv[])
{
  const MyStruct r = GetVar();
  std::cout << "Result: " << r.i << " " << r.j << " " << r.floats[0] << std::endl;
  return 0;
}

If you run this in debug, you’ll get :

First
Move
42 24 76

And in Release you’ll get :

First
42 24 76

Saving the copy that can be costly. You get the same behavior with or without the explicit copy or move constructor. The move constructor is used by default if defined.

So the lesson is: don’t stop yourself from returning structures, but be aware that the code won’t flow the same in debug and release.

Posted in C++, Coding, Snippet | Tagged | Leave a comment