Sunday, November 16, 2008
Tuesday, November 11, 2008
Chalana - ASF to MEL converter

What is Chalana ?
Chalana is a freeware program which you can use to convert AMC and ASF file to MEL so you can import the motion capture data into Maya.
How does it work ?
Chalana works by using the Biomichanics inc's AMC to MEL and ASF to MOV executables which you can download for free at CMU Graphics Lab motion capture database. Chalana also includes the same programs in the application directory.
With Chalana you can convert the MEL files generated by the above programs in to your Maya projects frame rate and/or grid scale.
For whom ?
Chalana can be used by Anyone who wishes to insert motion capture data to their animation. Especially for game developers and crowd animators.
Hair plug-in
This is my hair plug-in.
At first I didn't make the plug-in for hair (the third movie is the closest one to the original purpose) but called it so later since it looked like hair, when I made it Maya was 4 and there was no hair.



Sunday, November 9, 2008
Why are there so many symbolic links?
Why are there so many symbolic links? Beta
This document is still beta.
If you find anything is wrong or inaccurate, please let me know.
You can see lots of symbolic links to shared libraries on Linux. Why are there so many and how it works? I couldn't find a detailed explanation on the web so I'll try to make a very easy tut here.
In short they are there for version control of the shared libraries. The key is that there are two types of library modifications, implementation modification with no interface change of a library, and interface modification. An "interface" of a function, classes, etc. is the meaning of it. If the declaration has been changed, like
old: void foo(int bar);
new: void foo(double bar);
You can say the interface of the function has been changed. And even if there's no change of the declaration, the interface may have been changed. It gets changed if the meaning of the argument or return value has been changed.
old: void foo(int bar); //bar means your age.
new: void foo(int bar); //bar means the number of chocolate bars you have eaten today.
and an "implementation" means how the function that satisfies the interface is made. You can make a sort function using bubblesort, heapsort, quicksort, or bogosort ;) all have the same interface but implementations are different. A modification to a function implementation with no interface change is often made for bug fix and performance tuning.
I will first tell you how it works and then why it works.
How it works
[Three types of names]
There are three types of names for one shared library.
(1)libfoo.so
(2)libfoo.so.1
(3)libfoo.so.1.0
Usually (1) and (2) are symbolic links. libfoo.so -> libfoo.so.1 -> libfoo.so.1.0
(1)libfoo.so
It is called "linker name". It is used when building (linking) a shared library like
gcc -lfoo -o myapp *.o
(2)libfoo.so.1
It is called "soname". th number indicates interface version. It is incremented on every interface modification of the library. A program that uses the library doesn't always assume the latest interface, since the program may only work on old interface. Remember an interface means the meaning of the function. In a shared library, its soname can be embedded (i.e. information about the interface version of the library is held in the library itself) by building (linking) like
gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0 *.o
(the reason is described later).
(3)libfoo.so.1.0
It is called "real name". It is (usually) not a symbolic link. The first number (in this case 1) is the interface version of the library which is correspondent to the soname, and the second number (and sometimes the third) indicates the implementation version of the library, which gets incremented on every implementation modification of the library, like libfoo.so.1.1, libfoo.so.1.2 All the programs that use the library assume the latest implementation version of the library.
[When linking]
When a program (myapp) is built, like
gcc -lfoo -o myapp *.o
libfoo.so is searched and used (unless libfoo.a is found first). libfoo.so is a symbolic link: libfoo.so -> libfoo.so.1 -> libfoo.so.1.0 so what is really used is libfoo.so.1.0 The linker finds its soname libfoo.so.1, which is embedded in the libfoo.so.1.0, and put the soname to the executable (myapp) as a library that the executable is dependent on. It will sound a roundabout way but you'll see why the linker do such a thing when you've finished reading this blog entry.
[At the start up of myapp execution]
When myapp is started, libfoo.so.1 is searched because the name (soname) is recorded in myapp as a dependent library. Because libfoo.so.1 is a symbolic link to libfoo.so.1.0, libfoo.so.1.0 is loaded and used.
Why it works
Why is it good for the library's version control? I'll explain it by taking examples.
[When libfoo has a bug]
The library's author fixes the bug and release it as libfoo.so.1.1
gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.1 *.o
Because the interface is not changed, soname is not changed. Now libfoo.so.1.1 is the latest and the libfoo.so.1 's link should be updated.
old: libfoo.so.1 -> libfoo.so.1.0
new: libfoo.so.1 -> libfoo.so.1.1
This link is done by the system automatically (When you restart linux a program called ldconfig is executed, ldconfig finds wrong links and updates them). Now myapp uses libfoo.so.1.1 because libfoo.so.1 is a symbolic link to libfoo.so.1.1 In this way my app uses the latest implementation version of the library.
[When libfoo has a interface modification]
The library's author makes a new libfoo which has a different interface and release it as libfoo.so.2.0
gcc -shared -Wl,-soname,libfoo.so.2 -o libfoo.so.2.0 *.o
Because the interface has been changed, its soname should be updated (libfoo.so.2). Now a symbolic link libfoo.so.2 -> libfoo.so.2.0 is created. If he rebuilds myapp like before
gcc -lfoo -o myapp *.o
and runs it, libfoo.so.1.1 is still used, because myapp is still told to be dependent on libfoo.so.1 (because libfoo.so -> libfoo.so.1 when building) and libfoo.so.1 is still a symbolic link to libfoo.so.1.1
[When myapp's author wants to test the new library]
He wants to test the new library. He wants to make "yourapp" which uses the new libfoo. He can do so by changing the symbolic link libfoo.so
old: libfoo.so -> libfoo.so.1
new: libfoo.so -> libfoo.so.2
When he builds yourapp
gcc -lfoo -o yourapp *.o
and runs it. Now libfoo.so is a symbolic link to libfoo.so -> libfoo.so.2 -> libfoo.so.2.0, soname libfoo.so.2 is embedded in libfoo.so.2.0, and libfoo.so.2 is recorded in yourapp as a dependent library. On yourapp application startup, libfoo.so.2 -> libfoo.so.2.0 is loaded and used. myapp still uses libfoo.so.1 unless he rebuilds it after libfoo.so -> libfoo.so.2 relinking.
Conclusion
Every executable uses the latest implementation of a fixed interface which is recorded as a "soname" in the executable.
The soname which is recorded in an executable is the one that the symbolic link which name is "linker name" links to.
Saturday, November 8, 2008
Hooking library calls on Mac using DYLD_INSERT_LIBRARIES
Mac offers a way to override functions in a shared library with DYLD_INSERT_LIBRARIES environment variable (which is similar to LD_PRELOAD on Linux). When you make a twin brother of a function that is defined in an existing shared library, put it in you a shared library, and you register your shared library name in DYLD_INSERT_LIBRARIES, your function is used instead of the original one. This is my simple test. Here I've replaced f() in mysharedlib.dylib with f() in openhook.dylib.
$ cat mysharedlib.h
void f();
$ cat mysharedlib.c
#include <stdio.h>
#include "mysharedlib.h"
void f()
{
printf("hello");
}
$ cat main.c
#include <stdio.h>
#include "mysharedlib.h"
int main()
{
f();
return 0;
}
$ cat openhook.c
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>
#include "mysharedlib.h"
typedef void (*fType)();
static void (*real_f)() = NULL;
void f()
{
if ( ! real_f)
{
void* handle = dlopen("mysharedlib.dylib", RTLD_NOW);
real_f = (fType)dlsym(handle, "f");
if ( ! real_f) printf("NG");
}
printf("--------zzz--------");
real_f();
}
$ cat bat
#!/bin/bash
gcc -flat_namespace -dynamiclib -o openhook.dylib openhook.c
gcc -dynamiclib -o mysharedlib.dylib mysharedlib.c
gcc mysharedlib.dylib main.c
export DYLD_FORCE_FLAT_NAMESPACE=
export DYLD_INSERT_LIBRARIES=openhook.dylib
./a.out
$ ./bat
--------zzz--------hello
You also need to define DYLD_FORCE_FLAT_NAMESPACE (doesn't matter what value it has). In general it makes the command (in this case a.out) unstable, not a lot in my opinion if we use it just for debugging purpose, but it increases the chance of symbol name conflicts.
You can use the same technique to override a method in a C++ class. Say there's a method named "fff" in a class AAA, like
class AAA
{
public:
int m;
AAA(){m = 1234;}
void fff(int a);
};
To override it, you first need to know the mangled symbol name of the method.
$ nm somelibrary.dylib | grep "T "
00000ed6 T __ZN3AAA3fffEi
Then what you need to define is _ZN3AAA3fffEi. Don't forget removing the first '_'. If you see multiple symbols in the shared library and not sure which one to override, you can check it by demangling a symbol like
$ c++filt __ZN3AAA3fffEi
AAA::fff(int)
Now you can override it like this.
$ cat mysharedlib.h
class AAA
{
public:
int m;
AAA(){m = 1234;}
void fff(int a);
};
$ cat mysharedlib.cpp
#include <stdio.h>
#include "mysharedlib.h"
void AAA::fff(int a)
{
printf("--ORIGINAL:%d--", a);
}
$ cat main.cpp
#include <stdio.h>
#include "mysharedlib.h"
int main()
{
AAA a;
printf("--------main1--------");
a.fff(50);
printf("--------main2--------");
return 0;
}
$ cat openhook.cpp
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>
#include "mysharedlib.h"
typedef void (*AAAfffType)(AAA*, int);
static void (*real_AAAfff)(AAA*, int);
extern "C"
{
void _ZN3AAA3fffEi(AAA* a, int b)
{
printf("--------AAA::fff--------");
printf("%d, %d", b, a->m);
void* handle = dlopen("mysharedlib.dylib", RTLD_NOW);
real_AAAfff = (AAAfffType)dlsym(handle, "_ZN3AAA3fffEi");
if (real_AAAfff) printf("OK");
real_AAAfff(a, b);
}
}
$ cat bat
#!/bin/bash
gcc -flat_namespace -dynamiclib -lstdc++ -o openhook.dylib openhook.cpp
gcc -dynamiclib -lstdc++ -o mysharedlib.dylib mysharedlib.cpp
gcc -lstdc++ mysharedlib.dylib main.cpp
export DYLD_FORCE_FLAT_NAMESPACE=
export DYLD_INSERT_LIBRARIES=openhook.dylib
./a.out
$ ./bat
--------main1----------------AAA::fff--------50, 1234OK--ORIGINAL:50----------main2--------
Note that the first argument of the function call is this pointer, just like Python passes self to a bound method. C++ just does it implicitely. I believe this is compiler (in this case gcc) implementation specific, and there may be a case it is not true. Please use this technique at your own risk.
Here I assumed you have access to the header file that declares the function to get (the size of) argument data being passed to the function. If the size of arguments are all known (int, float, pointer, ...) you can wrap it even if you don't have the header but if not, you'll need to write assembler to modify the stack to pass the arguments to the original function.
Sunday, November 2, 2008
So how do I use Shake Command Window?
I use it for plug-in development. You don't have to restart Shake every time you modify a code. You can see the internal state of nodes interactively, you can test your plug-in after modifying the node state, and you can see how things work, monitor plug changes to see if node evaluation chain is working as you expected. There are two programs I was mainly using. I made these two programs bit by bit interactively with the Command Window.
[dispTree] Displays a node tree.
name: the root tree
recurseNode: set true if you want to show child node
showPlug: set true if you also want to show plugs and their values
recursePlug: set true if you want to show child plugs and their values
[dispPlugInfo] displays informations about a plug
nodename: node name which has the plug to display
plugname: plug name to display
You may need to add include directives to the header include (settings - header include).
#include <string>, etc.
[dispTree]
const char* name = "NRiScript1";
bool recurseNode = true;
bool showPlug = false;
bool recursePlug = false;
#define print(x) NRiSys::error((NRiName() + x).getString());
const NRiName operator +(const NRiName lhs, const std::string rhs)
{
return lhs + rhs.c_str();
}
void printSpace(int nestcount)
{
for (int n = 0; n < nestcount; ++n)
{
print(" ");
}
}
void dispPlug(NRiPlug* p)
{
NRiName val;
switch(p->getType())
{
case kString:
val = p->asString();
break;
case kInt:
val = p->asInt();
break;
case kFloat:
val = p->asFloat();
break;
case kDouble:
val = p->asDouble();
break;
case kPtr:
val.sprintf("0x%x", p->asPtr());
break;
default:
break;
}
print(".." + p->getName() + "=" + val + "\n");
}
void dispPlugTree(NRiPlug* plug, int nestcount, bool recursePlug)
{
printSpace(nestcount);
dispPlug(plug);
if (recursePlug)
{
int ncp = plug->getNbChildren();
for (int i = 0; i < ncp; ++i)
{
dispPlugTree(plug->getNthChild(i), nestcount + 1, recursePlug);
}
}
}
void dispNodeTree(NRiNode* node, int nestcount, bool showPlug, bool recurseNode = false, bool recursePlug = false)
{
printSpace(nestcount);
print(node->getName() + ":" + node->getClassName() + "\n");
if (showPlug)
{
int np = node->getNbPlugs();
for (int ip = 0; ip < np; ++ip)
{
dispPlugTree(node->getNthPlug(ip), nestcount + 1, recursePlug);
}
}
if (recurseNode)
{
int numkids = node->getNbChildren();
for (int i = 0; i < numkids; ++i)
{
dispNodeTree(node->getNthChild(i), nestcount + 1, showPlug, recurseNode, recursePlug);
}
}
}
void shakeCommandWinEntryFunc()
{
NRiNode* node = NRiNode::findNode(name);
dispNodeTree(node, 0, showPlug, recurseNode, recursePlug);
}
[dispPlugInfo]
const char* nodename = "NRiScript1.Gamma1";
const char* plugname = "In";
#define print(x) NRiSys::error((NRiName() + x).getString());
NRiName value(NRiPlug* p)
{
NRiName val;
switch(p->getType())
{
case kString:
val = p->asString();
break;
case kInt:
val = p->asInt();
break;
case kFloat:
val = p->asFloat();
break;
case kDouble:
val = p->asDouble();
break;
case kPtr:
val.sprintf("0x%x", p->asPtr());
break;
default:
break;
}
return val;
}
NRiName ioString(NRiPlug* p)
{
const char* types[] = {"ng", "in", "out", "inout"};
return types[p->getIO()];
}
NRiName typeString(NRiPlug* p)
{
switch(p->getType())
{
case kInt:
return "int";
case kFloat:
return "float";
case kPtr:
return "ptr";
case kString:
return "string";
default:
return "ng";
}
}
NRiName flagString(NRiPlug* p)
{
NRiPlug::Flags flags[] = {NRiPlug::kInternal, NRiPlug::kNotify, NRiPlug::kNotifyConnect,
NRiPlug::kInherit, NRiPlug::kDisconnectOnSet, NRiPlug::kPersistent,
NRiPlug::kRecompile, NRiPlug::kLoadable, NRiPlug::kPreUpdate,
NRiPlug::kOwnerScope, NRiPlug::kIgnoreConnect, NRiPlug::kAutoPlug,
NRiPlug::kLocal, NRiPlug::kIgnoreDependencies, NRiPlug::kDeleting,
NRiPlug::kXReadWrite, NRiPlug::kIgnoreType, NRiPlug::kAlwaysCallOwner,
NRiPlug::kMonitor, NRiPlug::kNoExpr, NRiPlug::kInterrupt, NRiPlug::kFiltered,
NRiPlug::kSerializeChildren, NRiPlug::kLookupSrc, NRiPlug::kExpressionSrc,
NRiPlug::kUserDefined, NRiPlug::kPassThrough, NRiPlug::kCurveDefined,
NRiPlug::kLocked};
const char* flagStrings[] = {
"Internal", "Notify", "NotifyConnect", "Inherit", "DisconnectOnSet",
"Persistent", "Recompile", "Loadable", "PreUpdate", "OwnerScope",
"IgnoreConnect", "AutoPlug", "Local", "IgnoreDependencies", "Deleting",
"XReadWrite", "IgnoreType", "AlwaysCallOwner", "Monitor", "NoExpr",
"Interrupt", "Filtered", "SerializeChildren", "LookupSrc", "ExpressionSrc",
"UserDefined", "PassThrough", "CurveDefined", "Locked"};
NRiName result;
for (int i = 0; i < 29; ++i)
{
if (p->getFlag(flags[i]))
{
result += flagStrings[i];
result += " ";
}
}
return result;
}
NRiName hasErrorString(NRiPlug* p)
{
if (p->hasError())
{
return "Yes";
}
else
{
return "No";
}
}
void printPlug(NRiPlug* p)
{
if (p)
{
print(p->getOwner()->getFullName() + ".." + p->getFullName());
}
print("\n");
}
void printPA(const NRiPArray < NRiPlug >& pa)
{
for(unsigned i = 0; i < pa.getLength(); ++i)
{
print(" ");
printPlug(pa[i]);
}
}
void shakeCommandWinEntryFunc()
{
NRiNode* node = NRiNode::findNode(nodename);
if ( ! node)
{
print("Node not found.\n");
return;
}
NRiPlug* plug = node->getPlug(plugname);
if ( ! plug)
{
print("Plug not found.\n");
return;
}
print("<<<");
print(node->getFullName() + ".." + plug->getFullName() + ">>>\n");
print(NRiName() + "[Value] " + value(plug) + "\n");
print(NRiName() + "[Expr] " + plug->asExpr() + "\n");
print(NRiName() + "[IO] " + ioString(plug) + "\n");
print(NRiName() + "[Type] " + typeString(plug) + "\n");
print(NRiName() + "[Flags] " + flagString(plug) + "\n");
print(NRiName() + "[HasError] " + hasErrorString(plug) + "\n");
print("[Input] ");
printPlug(plug->getInput());
print("[LogicalInput] ");
printPlug(plug->getLogicalInput());
//print("[Ouput] ");
//printPlug(plug->getOutput());
print("[Outputs]...\n");
NRiPArray < NRiPlug > pa;
plug->getOutputs(pa);
printPA(pa);
pa.clear();
print("[getLogicalOutputs]...\n");
plug->getLogicalOutputs(pa);
printPA(pa);
pa.clear();
print("[getDependencies]...\n");
const NRiPArray < NRiPlug > * pap;
pap = plug->getDependencies();
printPA(*pap);
print("[getDependents]...\n");
pap = plug->getDependents();
printPA(*pap);
}
Nice blog
Today I found a nice blog which was made by members of feeling software. I knew the company but didn't know they have started a blog. They are especially interested in image recognition including computer vision (reconstructing a model from images etc.), and interactive technologies. Because they have a sound knowledge of theories behind them, their words are quite realistic. Just browsing the blog will make you fun if you have no time to read all.
enlighten3d - An expert blog on computer vision and 3D graphics