Thursday, April 24, 2008
Conjugate gradient method is used in two ways.
1) Solving an optimization problem: obtaining the condition to minimize some function.
2) Solving a system of linear equations.
2) is an application of 1). First define a function which gets minimum when the equations is satisfied, then using 1), get the condition = the answer of the equations..
An excellent document about conjugate gradient method.
"An Introduction to the Conjugate Gradient Method Without the Agonizing Pain"
Anybody who starts learning conjuagate gradient method should start here.
This document should be registered as a world heritage.
Monday, April 21, 2008
This is a birds eye view of Houdini HDK class hierarchy I made it when I was having fun with Houdini apprentice last year. GD* classes are not shown here. Just for those who are learning HDK.
(Click the image for a larger size)
Note: They don't seem to be on the XSI blog anymore. It's a shame they were excellent.
This is a very good article about XSI scene graph.
Though it looks quite different, basically it's not so much different from Maya's dependency graph, it has connection, lazy evaluation with dirty. But an operator can modify data itself without caching, it should mean it has more freedom of designing caching mechanism when creating a custom operator, though it is more difficult to create one. And having an operator stack in a data object is good, you can see the construction history of a node at one place with the data itself. Letting us free from nasty reference data wrangling is also good.
I'm just wondering why FxTree (what is this? I'm not an XSI user) is a pure operator graph. There's a history about the birth of FxTree http://www.xsi-blog.com/archives/77#more-77 . Because it is usually not a good idea to mix two concepts, I just wonder if it is just a historical reason or it gets some benefits from being a pure operator graph.
Saturday, April 19, 2008
This blog entry is incomplete. Equations to get XYZ is wrong.
The other day I was asked how we could get the "difference" of two colors.
RGB value in a CG software is not proportional to what the monitor outputs due to gamma. So we will first correct it. We assume the monitor setting is sRGB. According to sRGB official document (IEC 61966-2-1) we will convert sRGB to XYZ,
We can convert an sRGB value to a linear-RGB value by
Wrong. Should use sRGB->linear-RGB equation.
Then convert it to XYZ.
Wrong. Should use linearRGB->XYZ equation.
if one ore more of R_liner, G_liner, B_linear value is less than 0.0031308, use
Wrong. Should use linearRGB->XYZ equation when linear value is small.instead only for that color(s).
To take color adaptation into account, L*a*b* requires "white point", i.e. ambient light color = your light on the ceiling. To adjust the XYZ colorwhere
- A: (Xn, Yn, Zn) = (109.851, 100, 35.582)
- B : (Xn, Yn, Zn) = (99.095, 100, 98.072)
- C : (Xn, Yn, Zn) = (98.072, 100, 118.225)
- D65: (Xn, Yn, Zn) = (98.072, 100, 108.892)
These are values I found on the net. I still cannot find the accurate way to calculate the value.
Then depending on the value of X', Y', or Z', again if one of more value of them is larger than 0.008856, useor if it is smaller, usefinally,Now you can use above (color diff) equation to get the difference of color.
Basically it is the same as what is written in Wikipedia (at least this moment), except that the Matrix in sRGB->XYZ calculation is a little bit different.
I found a super cool chromatic Adaptation demo. You can test your eyes' chromatic adaptation here.
In the middle of the page where you see two colors, yellow on the left and blue on the right and a little circle in the center, gaze the little circle for a while, then put the mouse over the area. It's amazing you can see the picture naturally.
Friday, April 18, 2008
There are several module/packages available when you make a server-client program.
asyncore is a Python standard module, i.e. when you install Python on your machine, you can use it immediately. Twisted is an open source project. They are both for server-client programs.
While I was making pyCommandPort, I tried not to use twisted, because it's just a small utility plug-in and twisted is too much overkill. I didn't want the force the users to install twisted on their machines, instead I used asyncore. I could do low level socket programming/multi thread programming but it was another bothering and time consuming work.
Actually asyncore and twisted are quite similar. Both of them have a single main dispatcher and user functions are called by the dispathcer. While asyncore is for only server-client type programs, twisted is for any programming that deals with blocking behavior i.e. behavior that needs to wait for some slow processes. Though twisted is typically used for network programming because server/client communication is a typical slow response, twisted's usage is not limited for that purpose.
One example is "Maya execution". I used MGlobal::executePythonCommandOnIdle() API. When it is called with a Python script as a parameter, Maya registers it in the internal queue of Python scripts, and when Maya had done everything (rendering, subdividing polygon, ...), it executes the queued Python scripts one by one, in the main thread. This is not Maya specific function, many framework has it, e.g. wxPython has equivalent function. wx.CallAfter() is the one. When you call MGlobal::executePythonCommandOnIdle(), you can never see when it is executed. It may be executed immediately, or tomorrow. I wanted to send the error message to the client of pyCommandPort server, and it is another type of 'slow response' behavior. Since asyncore is only for network programming, it cannot handle these problems nicely.
If it had been something like querying something to the database server instead of Maya execution, asyncore can handle it because accessing to a database server is a network programming, but in this case not. asyncore tries to do everything in the main thread, and the main thread cannot wait for Maya execution at the same time waiting for another incoming connection.
Twisted is much more flexible. I will write what a twisted programming is like on another post soon.
I found a weird Maya Python plug-in behavior yesterday.
When I make a plug-in like this,
and load it, it prints out
How come a method is defined in the built in module?
It means you cannot use global declaration.
You need to either import the plug-in module inside the code like,
pyCommandPort.someattribute = somevalue
or need to separate the code from the plug-in file and import it.
The globals() returns the right dictionary, and the class is not
in the builtin module. Looks Maya is doing some complicated things.
Thursday, April 17, 2008
Maya lets the user access to its scene over the network with commandPort. Recently I felt the need of sending Python command instead of MEL script. I could use commadnPort and use MEL commnd 'python' everytime but I didn't like the way. I searched highend3d for it. I found a tool 'mapy' http://www.highend3d.com/f/mapy but it's fully GUI based, and the source code doesn't seem to be open. So I made it myself. Since I used asyncore (one of Python module for easy network programming), currently it doesn't support multiple connections, and I made modification on purpose, it's somewhat different from Maya's standard commandPort.
Some of big differences are:
- You can open one port at a time.
- Close connection every time a command is executed and the error message is transmitted back.
- Only error messages are returned. (Currently it always returns null string when "MEL" is specified).
- Command is terminated until the server receives the terminator string.
(You may feel some of them big restrictions but for my usage it's enough ;)
To use the plug-in, just place everything in the plug-in dir and load pyCommandPort.py (not pyCommandPortImpl.py), then execute a MEL command (Why there are pyCommandPort and pyCommandPortImpl? I will write the reason on a different post).
It opens a port 7070 by default. You can see it's working using telnet command
telnet localhost 7070
then you'll see the result in the script editor
# print range(5) #
[0, 1, 2, 3, 4]
There are several flags available.
Address. e.g. "192.168.0.3", "localhost", "".
It defaults to "".
Port number. Any unused port number between 1024-65535 will do.
It defaults to 7070.
The command fails if the port is already used.
In that case use another number.
If this flag is specified, it stops the server.
Command terminator string.
It defaults to '\r\n' (i.e. enter)
"Python" or "MEL". Defaults to "Python"
On or off.
If on, it shows commands to be executed on the script
editor. It defaults to on.
Query sever settings. Use with other flags.
It returns value only when the server is running
I put the source code here. Note that this is still a beta version.