Friday, December 2, 2011

Autoload in SQLAlchemy

A quick tip,

If you want your data models to autoload their contents as you create them, you can use the following idiom:

I generally use three python modules in my database related (thus using SQLAlchemy) applications, one for the declarative Base (declarative.py), one for the database url, session, query and engine (db.py) and a last one for the models (models.py).

In the declarative.py:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

In the db.py:

from declarative import Base
engine = None
session = None
query = None
metadata = Base.metadata
database_url = None

def setup(url="sqlite:///:memory:"):
    global engine
    global session
    global query
    global metadata
    global database_url
    
    # to let my models to register them selfs 
    # and fill the Base.metadata
    import models
    
    database_url = url
    
    engine = sqlalchemy.create_engine(database_url, echo=False)
    
    # create the tables
    metadata.create_all(engine)
    
    # create the Session class
    Session = sqlalchemy.orm.sessionmaker(bind=engine)
    
    # create and save session object to session
    session = Session()
    query = session.query
    
    return session

Setting up the database becomes db.setup(), easy enough.

In the model.py:

import db
from declarative import Base

class MyClass(Base):
    __tablename__ = "MyClasses"
    id = Column(Integer, primary_key=True)
    name = Column(String(256), unique=True, nullable=False)
    description = Column(String)
    
    def __new__(cls, name):
        if name:
            # get the instance from the db
            if db.session is None:
                # create the session first
                db.setup()
            
            obj_db = db.query(MyClass).\
                         filter_by(name=name).first()
        
            if obj_db is not None:
                # return the database instance
            
                # skip the __init__
                obj_db.__skip_init__ = None
                
                return obj_db
        
        # if we are here,
        # it means that there is no instance
        # in the database with the given name
        # so just create one normally
        # And SQLAlchemy queries will use this part
        return super(MyClass, cls).__new__(cls, name)
    
    def __init__(self, name):
        # do not initialize if it is created from the DB
        if hasattr(self, "__skip_init__"):
            return
        
        self.name = name

In the above example the __init__ method is unnecessarily included to show how to skip the __init__ when there is an instance retrieved from the database.

The key in the above example is the usage of __new__ and using the super to hand the class creation to Type as shown above, this will trigger __init__. We can not just return because the class will not be initialized and we should skip the __init__ for instances returned from the database.

So by using this idiom, you should be able to restore an instance without querying it:

from model import MyClass
import db

db.setup()

myC1 = MyClass(name="Test")
myC1.description = "To show the instance retrieved correctly"
db.session.add(myC1)
db.session.commit()

myC2 = MyClass(name="Test")
print myC2.description
# this should print:
#     To show the instance retrieved correctly

Thats all, easy and smooth...

Edit: Now I need to note that SQLAlchemy also uses __new__ to create new instances, but we prevent it doing another query again inside __new__ by checking the name argument, which is not used by SQLAlchemy when restoring from database.

Sunday, November 6, 2011

My first iDevice

Last week, I recieved an iPad as a gift from my boss (I should not talk about what kind of nasty things that I had to do to get this gift ;) ), anyway now I've officially entered to the world of Apple.

First impression, I've liked it a lot. I was always talking about how much a tablet is useless for me because I have a smartphone and a laptop, but it seems that after getting it you start to find a lot of use for it.

Now I'm reading all my emails and news feeds (and writing this post) on iPad and I'm planning to sign up for magazines like 3D World (as I see there is no digital version of Cinefex for now).

I'm lucky because they didn't make fun about me that much at work, cause, as an Android fun and phone owner (SGS 2) even though I was always talking about how much I hate about Apple's money oriented policies, I always stated that as a tablet iPad is better than any android tablet (except the Advent Vega) and recommended iPad to anyone asking what to buy.

The only thing that I'm missing is the lack of Android grade sharing. In Android, the sharing functionality is something more universal than it is in iOS. For example, when you install an app that allows you to share something, it is automatically listed in the sharing targets. Like StumbleUpon, it is listed in any application that wants to share something. But in iOS, as I see, it is not working like that, the app needs to be programmed in that way to be able to use StumbleUpon as a sharing target. For now it is a big minus for iOS.

On the other hand, Eventhough it doesn't have dual core A5 CPU and the powerfull PowerVR SGX 543 GPU of iPad 2, I've liked the smoothness of the interface.

I definetely liked the battery life. I was able to use it for two days continously without recharging it. I am still amazed how long the battery stays in %100 even while watching video on the internet.

I very much liked the consistent style of iOS apps which is another nice feature that Android apps are missing.

I liked iPad...

Tuesday, November 1, 2011

Planning to switch to a Macbook Pro and OSX

I'm still using my HP HDX 18 notebook, it is 3 years old now. And last year I bought a Macbook Pro 13 for my wife, ever since that time I felt pure envy. So I decided to buy a Macbook Pro 17 to myself when the Pre-2012 versions become available.

Because I hate using two operating systems at the same time (aka dual boot) I need to decide which operating system I should use, Ubuntu or OSX. So I thought listing what I like and hate will help to choose one.

What I like about MBP and OSX:
  • The build quality of Macbooks are incredible.
  • Multi-touch trackpad is awesome. After using my wifes macbook pro a couple of minutes and switch back to mine, I still tend to keep scrolling with two fingers (very intuitive), which is obviously not working.
  • OSX has better support to MBP hardware (arguable)
  • You can get more juice out of your battery (even with powertop and custom hacks under linux you get around 6 hours where as you get 7-10 hours in OSX)
  • Wake up and sleep are incredible, still can not believe how fast it sleeps and wakes up (inevitable)
  • Native gamma adjustment tool is incredible, still can not get correct gamma response under linux with the only tool for me is nvidia control panel (need more r&d on this subject)
  • All Adobe programs (Photoshop and Lightroom mostly) are working natively (but I need to state that I hate Adobe), using alternatives like Gimp sometimes doesn't satisfy your needs as CMYK files can not be read in Gimp and trying to give a chance to Wine will leave you with no pressure sensitivity under PS CS 5, CS3 works fine though and for Bibble, eventough their creative photo retouching tools are absolutely better than Lightroom (I think it is because Lightroom doesn't want to step into Photoshop's shoes) I'm still not liking the vibrance tool in bibble (it is more or less like saturation where it should not change the skin colors) and the performance in linux compared to windows is very slow.
  • Diablo III will work natively under OSX where as under linux the only chance to get this adorable piece of art to work is Wine, although wine is very nice and most of the time smooth, running a windows program with wine is not comparable to running it nativeley under OSX (I wouldn't think that I was going to say that I'm liking an os because of a game but it is true I'm very excited about Diablo III)
  • OSX is based on FreeBSD, so you will feel at home with the terminal and shell commands
  • It has the same tools with linux like rsync so my backup script will still going to work (o-oh I forgot that OSX doesn't support ext4 and my external backup drive is using EXT4, so I need to convert it to EXT2 or HFS or something else)
  • space/preview is working adorably (Gnome-Sushi is not working that flawless)
  • drag&drop was not so fun before
  • The way that the applications are installed and placed on a consistent place (/Applicatons)
  • Pycharm and WingIDE are working in the same way as they are in linux.
What I don't like about MBP and OSX:
  • No numeric pad, so it seems that I need to get use to it (no deal breaker)
  • Houdini under OSX doesn't support Qt and PyQt4, at least I couldn't manage to run it, even though I compiled the Qt, Sip and PyQt4 against houdini's python 2.6 (this was the deal breaker for me, when I was trying to finish a project on a Mac Pro and OSX, where in the middle of the night I installed Ubuntu and 30 minutes later of my switch I was working happily under linux with everything working smoothly)
  • Another for Qt, compiling it for Maya 2012 OSX and then writing a bash script to link all the dylibs to Nuke's Qt libs took like 3-4 days to figure out, where as under linux it is enough to copy the PyQt4 folder and the Sip related files to nukes site-packages folder, and as I mentioned before Qt is not working for Houdini OSX (may be I'm missing something).
  • No apt_get, this is a horrible deal breaker, I heard about macports, but they say that time to time it will leave you with broken packages where you can't downgrade nor upgrade.
  • The OSX community is not very technical compared to linux (though there are very successful open source package developers who are using OSX), it becomes very important if you try to build a pipeline over the three operating systems and can not find a solution for something very simple.
  • Application based alt+tab switching still confuses me how do you switch between windows of the same program, expose? (but I've liked the gnome-shell implementation, where you can use the arrow key after alt+tab while holding alt key) As Chris has pointed using command+~ (tilde) switches between the windows of the same application and I found that using command+tab and arrow keys shows the preview of the windows of the chosen application, so I think I'm going to be fine when I start using osx, apparently it the lack of information that hardens my experience in osx. 
  • May be I'm missing something but why the green plus button on the tittle bar is not maximizing the window to the screen sometimes. Seems that it is fixed or working as predicted in OSX Lion.
On the other hand, there are couple of things annoying me in linux:
  • like the high cpu usage bug which is still not solved for the last 3 years I was in the linux world
  • I slowly started to feel tired about always fixing something
  • It started to feel like it is not complete as a package
  • Applications are spread out all over the system, you can find things installed under /usr, /usr/local, /usr/local/share, /usr/share, /opt/, /var, /var/local, /var/opt etc.
  • still can not solve the Samba speed issue, and NFS is using UTF-8 in Linux and ANSI in Windows, so having a windows server with NFS, any Turkish characters in the filenames (which means that I need to kill somebody by the way) will leave you with a file name with "?" characters in the best condition.
  • others mentioned above
But I need to state that I'm in love with Ubuntu and if I finally decide to switch to OSX completely, it is going to be like tearing my heart off, if I will not turn back in 2 weeks.

But change is good time to time. So it seems like I'm going to give another chance to OSX besides, it was Houdini who made me left OSX before ;)

posted from Bloggeroid

Monday, September 19, 2011

Switched to PyCharm

I was using WingIDE for the last 2 years and I loved it. It was and it still is a great Python IDE. Recently in the mailing list of WingIDE they were talking about how great PyCharm is and what is missing in WingIDE and where PyCharm fails.

Anyway I downloaded the trial version of PyCharm and started to use it. At the beginning I hate it. Basically it felt slow and there were couple of other things that I was very much used to use in WingIDE and they were missing in PyCharm (it was my mistake, they were all present but I need to search for them).

I didn't touch it for 2 weeks and then after what, I don't remember, I've opened it up again and started to read the quick tips. And I found that all the things that made me to switch back to WingIDE was there. And there were a lot more things which are enhanced and working properly in PyCharm and it supports more languages, has tons of options to customize the way it works etc. Somehow I felt that even the program feels slower, I'm coding faster. There are tons of shortcuts for TDD development, you need to watch this video.

There is a "Back to school office sale" where you can buy the personal version of PyCharm for $49 instead of $99. Which is very much reasonable when you think that I paid $230 for WingIDE ( $195 Wing IDE 3 + $35 to upgrade to WingIDE 4, but the latest price for WingIDE Pro 4 - Non Commercial is $95 which is in the same margin with PyCharm Personal without the discount.).

So I bought PyCharm and I'm very happy using it.

Wednesday, April 13, 2011

Houdini BUG: ERROR: Couldn't open "Fuse11.0.658/FUSE_ColorOptions.ui" for reading

This is a bug report I've created for Houdini 11.0.658 and it also gives a workaround for the problem. I'm publishing it here cause there is no solution on the web (or at least I couldn't found any).

Under Mac OSX 10.6.6 setting HOUDINI_PATH environment variable to a path either in ~/.profile or in .MacOSX/environment.plist causes Houdini to crash on startup. The terminal outputs the following error messages:


Stereo1s-Mac-Pro:MacOS stereo1$ echo $HOUDINI_PATH
/Users/Servers/Shared/M/DEV/houdini
Stereo1s-Mac-Pro:MacOS stereo1$ pwd
/Applications/Houdini 11.0.658/Houdini.app/Contents/MacOS
Stereo1s-Mac-Pro:MacOS stereo1$ ./houdini
ERROR: Couldn't open resource file "resources" (No such file or directory)
Can't open dophints.cmd
ERROR: Couldn't open "Fuse11.0.658/FUSE_ColorOptions.ui" for reading: No such file or directory
Color name 'ListEntry1' is missing from the theme.
Color name 'ListEntry2' is missing from the theme.
Couldn't find font Proportional.12 - using default instead
Couldn't find font Proportional.9 - using default instead
Couldn't find font Proportional.9 - using default instead
Couldn't find font Proportional.9 - using default instead
Couldn't find font Proportional.9 - using default instead
Couldn't find font Proportional.9 - using default instead
Couldn't find font Proportional.9 - using default instead
Couldn't find font Proportional.9 - using default instead
(and this last line repeats around 100 times)


and adding "/Library/Frameworks/Houdini.framework/Versions/11.0.658/Resources/houdini" to HOUDINI_PATH at least lets houdini to open properly but the interface is not looking the same before (I think it is not loading my personal preferences this time).

To fix the preferences issue then I have also added "$HOME/Library/Preferences/houdini/11.0:/Users/Shared/houdini/11.0:$HIP/houdini" to the HOUDINI_PATH and everything works as expected right now.

So the final HOUDINI_PATH looks like this:

HOUDINI_PATH=/Library/Frameworks/Houdini.framework/Versions/11.0.658/Resources/houdini:$HOME/Library/Preferences/houdini/11.0:/Users/Shared/houdini/11.0:$HIP/houdini:/Users/Shared/Servers/M/DEV/houdini

But under Windows setting the HOUDINI_PATH didn't cause any problem like that.

Monday, January 17, 2011

Taking The Pleasure of Suspend/Hibernate on Ubuntu

Suspend and Hibernate had always been a problem with my laptop in Ubuntu. I believe I've finally fixed it.

I first tried to use the s2disk and s2ram tools which are installed with uswsusp (sudo apt-get install uswsusp). It fixed my hibernation but not suspend. I then, tried a couple of tweaks suggested in this page. But it didn't fixed my suspend problem again (though the settings are still present, I think they are helping me anyway).

Then I downloaded the latest bios+flash utility from HP. But, there was a problem, the utility is written for Windows.

I tried to search for information about how to flash bios under linux, there is a nice forum page here, but I didn't try to use these methods cause I was not sure if my laptops flash utility was going to work under FreeDOS (but in the installation program it say it is working under FreeDOS-XP-2000-Vista-7, thanks to HP not sharing this information).

Then I found a Windows XP Live CD edition (not sure if it is legal) which nicely worked, and voila I've flashed the latest bios and all my suspend problems went away.

I'm now taking the pleasure of being able to suspend and resume my laptop without a problem.

Saturday, November 27, 2010

Back to Ubuntu :)

All right, I'm back to Ubuntu again. I'm so much surprised how much I've missed that little one. After playing with Kubuntu for the last 1.5 year, coming back to Ubuntu feels much better right now. I know that it is very much a personal taste to have one of them but Gnome feels much better, solid and faster after playing with KDE for a long time. Lately Kubuntu started to feel laggish. And previously I was kinda forced to move to KDE because of the sticky key problem I was having under Maya 2009. And with the new Qt interface of Maya 2011 I don't really have anything chaining me to KDE any more.

So, I consider myself greeted by my Ubuntu fellas.

And a note about my move, if you want to do the same thing and want to move from Kubuntu to Ubuntu, just insall ubuntu-desktop by using:

sudo apt-get install ubuntu-desktop

then if you don't like to have the kde programs you can remove them or there a couple of ways to have kde and gdm together and don't have ones program listed in other ones menu.

Friday, November 12, 2010

Sleeping Princess - Prensesin Uykusu

My first movie will be out there in the theatres next weekend. I participated to the movie as being the Visual Effects Supervisor and also the Lead Technical Director.

I would love to dive in to the technical challenges we've been through, but I will just give some screen shots from the movie this time.

Just go and watch the movie, it's a good one from the great director Cagan Irmak.



















































































Tuesday, October 19, 2010

Code Annoyance - mocker mock Mocker Mock

The documentation of the Python Mocker library sucks. The example codes doesn't show the import statements at the beginning of the example, and they use the mocker (which is also the name of the package) as a variable inside the example, so you get double frustrated.

here is the example directly taken from the documentation of the library:
>>> mocker = Mocker()
>>> obj = mocker.mock()

>>> obj.hello()
>>> mocker.result("Hi!")

>>> mocker.replay()

>>> obj.hello()
'Hi!'

>>> obj.bye()
Traceback (most recent call last):
...
mocker.MatchError: [Mocker] Unexpected expression: obj.bye

>>> mocker.restore()
>>> mocker.verify()

the first weird thing is also the first line of the example code:
mocker = Mocker()

the second one is also the second line of the example code:
obj = mocker.mock()

all right, I can see that because the statement mocker now corresponds to a Mocker object the mocker.mock() should be returning a mock object (did you get my frustration, mocker mock Mocker Mock, wtf!)

what those guys written this documentation has forgotten should be a line of:
from mocker import *

and knowing this really doesn't help me too much, cause I don't code in this way. Really, who is importing everything to the module namespace should be doing something evil.

and also using the package name as a variable to hold an object which is produced by one of the classes of that package means you are really shitting in the namespace...

and I see a lot of this kind of namespace killer statements in package documentations, I think they think that is much clearer, but it is wrong, cause it really breaks the way I construct things in my mind.

I'm frustrated... or am I missing something...

EDIT:
As muhuk warned me about contributing an OpenSource package before complaining about its defects I created a bug report explaining my concerns. You can find the bug report here:
https://bugs.launchpad.net/mocker/+bug/663821

I need to thank to muhuk

Friday, October 15, 2010

Quick Tip: Setting The Render Image Format in Maya

To set the render image format to OpenEXR you need to set both the imageFormat and imfkey in defaultRenderGlobals. Setting the imageFormat to 51 means that you are going to use a custom image format like Tiff Uncompressed (tif), hdr, exr, Zpic, picture, ppm, ps etc.. and than you set the imfkey to whatever format you want, in my case I set it to 'exr'

from pymel import core as pm
dRG = pm.PyNode('defaultRenderGlobals')
dRG.setAttr('imageFormat', 51)
dRG.setAttr('imfkey', 'exr')
Edit: Also you can set the compression to ZIP ("Zip (1 scanline)" in Nuke terms) by:
mrG = pm.PyNode("mentalrayGlobals")
mrG.setAttr("imageCompression", 4)

Thursday, September 2, 2010

Round Corners in Houdini

It's been a while since my last post, sorry about that...

I was playing with Houdini for the last 1 year, did a couple of jobs with it. It saved my ass a couple of times and I can say that I completely felt in love with it, and I really felt sorry for the years I spent without Houdini. Anyway, after a while later I decided to try to complete the jobs more and more with Houdini and try to go away from Maya a little bit. I'm not going to enter the valley of the differences of the two programs and how awesome Houdini is etc. but I need to say that it feels awesome.

Yet, there is another job that I need to finish up (the deadline is tomorrow). The job is about a tire brand etc. Lets cut the chase, the object was not looking good just because they've sent us the production model that they are using to produce the product in the factory, and you now this kind of nurbs models are a little bit too perfect, has sharp edges and a lot of details. In Maya, to break this perfection, I generally use the round corner shader to smooth the sharp edges and it works perfectly. But in Houdini you don't have this kind of already built in shader but you have the powerful VEX.

I've first searched for it on the web, there was microBevel from Simon Barrick but it was not working with Houdini 11 (by the way I need to thank Simon, for his fast and friendly responses to my e-mails).

Then I tried to find a paper about how to smooth edges of geometries in render time. And I found a document about the round corner shader in mental ray from Hakan Andersson (the famous master zap). So it was pretty obvious actually...

you can download the OTLs here:
tangent.otl
roundCorners.otl

Here are the results of my round corner OTL with different curving choices:



and here, the tire with and without round corner shader:

Sunday, June 6, 2010

A new Property idiom in Python

There are really smart guys around the world, especially in python world. One of these guys (Sean Ross) suggested this to be used instead of the regular property in python:

"""
Rather than defining your get/set/del methods at the class level, as is usually done, e.g.

class MyClass(object):
def __init__(self):
self._foo = "foo"

def getfoo(self):
return self._foo
def setfoo(self, value):
self._foo = value
def delfoo(self):
del self._foo
foo = property(getfoo, setfoo, delfoo, "property foo's doc string")

I would like to suggest the following alternative idiom:
"""


class MyClass(object):
def __init__(self):
self._foo = "foo"
self._bar = "bar"

def foo():
doc = "property foo's doc string"
def fget(self):
return self._foo
def fset(self, value):
self._foo = value
def fdel(self):
del self._foo
return locals() # credit: David Niergarth
foo = property(**foo())

def bar():
doc = "bar is readonly"
def fget(self):
return self._bar
return locals()
bar = property(**bar())

I've started using these idiom and I'm happy to be able not to bloat my classes with getters and setters...

Monday, March 22, 2010

TaskJuggler

I've found the project management software of my life. TaskJuggler. How adorable piece of software this is. I strongly recommend TaskJuggler to anyone who needs a strong project management software which is open source and much more powerful than the commercial alternatives.

Here is a passage from their web site:

"TaskJuggler is a modern and powerful, Open Source project management tool. Its new approach to project planing and tracking is more flexible and superior to the commonly used Gantt chart editing tools. It has already been successfully used in many projects and scales easily to projects with hundreds of resources and thousands of tasks."

To use TaskJuggler, the only thing you need is a text editor and the taskJuggler's scheduler itself. You can start planing a project by writing about the project with the simple script like language of TaskJuggler.

They also provide a GUI. There are couple of downsides with that GUI though. The code-completion is not deeply aware of the TaskJuggler's language (or maybe I'm missing something). Although, it can complete simple text, it doesn't provide complex completion like an IDE can provide.

So for example, you can define a task (task1):

task task1 "Task1"

and create sub tasks (subTask1, subTask2 etc) under this main task:

task task1 "Task 1" {
   task subTask1 "Sub Task 1"
   task subTask2 "Sub Task 2"
   task subTask3 "Sub Task 3"
   # etc
}


then later in the project definition when you try to reach a sub task by writing "task1." I expect a list of tasks popping-up, but it is not, instead it waits until you enter 3 characters then it offers you a list of words starting with those letters, which are not always children of the original task. So you need to find the name by parsing the code by your-self, which is very annoying for even medium sized project files which spans over couple of hundreds of lines.

On the other hand, TaskJuggler designed for shell use, the gui is added later.

Another thing that makes me scratch my head is the new version under development, TaskJuggler 3. The down side (imho) of the new version is, it is developed under Ruby as a Ruby Gem. Which is very very nice for Ruby people. But I wished to have it with Python. If I had it under Python I could use it in my asset management system, to let my tool to have powerful management capabilities. And I can't imagine how fun will it be to use TakJuggler as a Python package under WingIDE. (See Edit 1)

On the other hand, its flexibility on every stage of project management is superior to other software's. I specially liked the part that you can define alternatives to resources with a lot of options which allows you precisely and efficiently allocate a resource.

You can use TaskJuggler as a project tracking tool too. You can refine an ongoing project till the delivery date etc.

Finally, I need to say that I loved that software and it was the tool I'm searching for the last 2 years. Thumbs up TJ people

Edit 1: On this page you can find a Python front-end of TaskJuggler. It is written for an old version of Python (2.3 I think). It seems, it needs to be updated.

Monday, March 1, 2010

Bye bye Windows 7 RC and Lightroom, Welcome Kubuntu and Bibble 5 Pro

You know it was getting closer... After March 1st (today), Windows 7 RC was not going to work any more... So I decided to cut my arm holding Windows 7 tightly... I've deleted the 3 NTFS partitions on my second hdd and created a fresh ext3 partition. Copied all my files back to the new partition, and edited the /etc/fstab to make it mounted on boot etc. I'm pure now...

I was using Windows just to edit my photos with Lightroom. It was evident that I need something else that works under Linux. I first tried to use Wine with no chance, at least for the last 8 months there was no version of Wine able to run Lightroom properly.

Recently, I came across with one software that works natively and perfectly under Linux, and even works faster than Lightroom (at least they say so, and indeed I felt the difference), the name of the magic was Bibble 5 Pro.

So, I've installed the trial version and tested it with my photos. It was working very nice, but definitely I need to get used to the interface, though it quite resembles the Lightroom interface, and I need to find a nice raw preset for my camera (Nikon D300 by the way). Bibble 5 has settings like "Product, Product Reduced, ..., Portrait, Portrait Reduced etc.", what I found is that Portrait preset is very close to my taste. Eventhough, I fell a little color cast on the photos. I don't know, I think I need to get used to it.

And my final words goes to Adobe. I don't understand them. Some how they create the programs which takes hefty amount of peoples attention, but, though they support another Unix platform like MaxOSX, they really resist hard to support Fedora/Debian Linux. It really hard to understand that, isn't that the same money we pay. So what is the matter. The best protest for myself is to stay away from Adobe and use alternatives as much as possible.

Thursday, December 31, 2009

Project and AssetManager

Followers of this blog should remember me talking about the production asset management system back in june this year. Since then I tried to find a nice way to handle the files in our studio. I looked the on-the-shelf tools like AlienBrain, Shotgun etc. But I wanted to have a system which is structurally not that much complex, and as open as it gets so I could instantly add new features to it. And I think, I was attracted by the idea of being the writer of an asset manager system. So I decided to write of my own system.

Those days we were using a simple MEL script to let Maya to decide where to save the file by looking a template folder structure stored in the file server. With some limitations, this little script was doing its job very well.

In my first attempts to an Asset Management system, I had a lot of ideas about what an asset manager should do and a little bit of idea about what it shouldn't do. I tried to gather those ideas to form a system, but I couldn't manage it. Somehow I couldn't do the thing. I drew graphical charts, schemas explaining the data flow, the program flow and the general structure and I started coding of the Asset class in Python. But again somehow I couldn't manage to have something meaningful. So I let it go.

Because, I couldn't do anything about coding of the asset manager, I decided to rewrite the ProjectCreator tool by using Python. It was originally written in C#. We were using this tool to create empty projects, with a predefined folder structure and with definite number of shots in some specific folders and to add new shots folders inside that project structure. The tool was written very badly around the interface code by myself. And because of the design, we were not able to change the project structure independently for one project to another. So I decided to have a proper object oriented system. Which also lets me to script the regular things like adding folders to all of the projects and sequences at once.

I've started coding of the classes those I'll going to need, like the Database, Project and the Sequence classes. They were doing some basic things. But, the Sequence class was especially special for me, because, some how I saw the way to the asset manager in it. While coding the Sequence class, it is connected it self to the Asset class I had written before. So the basic problem was solved. I had all my basic structures to form a very little living asset manager system.

At the beginning, it was just saving the files to proper folders with proper names (same thing with the previous MEL based system). I had to code an interface for it to let the artist to use it. I decided to use PyQt. We instantly switched to the new system.

In time, the system evolved to a python module and I named the system as AssetManager with peace of mind. The system is evolving very quickly. It is already doing things like, finding all the assets those a user did for a specific sequence or shot, tracks the file versions in a very simple but solid manner (by saving every version with a different version number :) and not letting the user to save over an old version), keeping track of the referenced asset, and updates the references automatically, tracks shot data like shot timings, shot descriptions etc.. The best part of the system is, it is working under any platform that Python is supported. It means, it works under Maya, Nuke and Houdini. And I'm trying to find a way to add it to Photoshop (probably I'm going to write some Java code for it). And while adding all of those features, I always tried to keep the generality of the code.

By having a working system like that, now it is much easier to think about the new features that the system needs. So, I can see the next two steps in front of me.

All the artist are very happy to be able to use a system like that, and they are keen to see new features coming constantly.

Saturday, December 12, 2009

Famous Maya Render Layer Bug

I bet you encountered that bug before, like all the others maya players around. I'm talking about the render layer bug, you now, you switch to some other layer and got some messages saying that maya couldn't create a connection to a shading engines foo attribute at index [-1], yeeahh :) this one I'm talking about... So here is the solution

The bad thing about it is, they just didn't fix the real problem, it is a workaround...

Saturday, October 10, 2009

Python Function Decorators 3: Input Based Caching

Below you can find an input based cache system implemented as a Python function decorator:

########################################################################
class InputBasedCachedMethod(object):
    """caches the result of a class method inside the instance based on the input
    """
    
    
    
    #----------------------------------------------------------------------
    def __init__(self, method):
        # record the unbound-method and the name
        #print "running __init__ in InputBasedCachedMethod"
        
        self._method = method
        self._name = method.__name__
        self._obj = None
        
        
        
    #----------------------------------------------------------------------
    def __get__(self, inst, cls):
        """use __get__ just to get the instance object
        """
        #print "running __get__ in InputBasedCachedMethod"
        
        self._obj = inst
        if not hasattr( self._obj, self._name + "._outputData" ):
            #print "creating the data"
            setattr ( self._obj, self._name + "._outputData", list() )
            setattr ( self._obj, self._name + "._inputData", list() )
            #print "finished creating data"
            
        return self
    
    
    
    #----------------------------------------------------------------------
    def __call__(self, *args, **keys):
        """for now it uses only one argument
        """
        #print "running __call__ in InputBasedCachedMethod"
        
        outputData = getattr( self._obj, self._name + "._outputData" )
        inputData = getattr( self._obj, self._name + "._inputData" )
        
        # combine args and keys
        argsKeysCombined = list()
        argsKeysCombined.append( args )
        argsKeysCombined.append( keys )
        
        if (not argsKeysCombined in inputData) or outputData == None:
            #print "calculating new data"
            data = self._method(self._obj, *args, **keys)
            inputData.append( argsKeysCombined )
            outputData.append( data )
            setattr( self._obj, self._name + "._inputdata", inputData )
            setattr( self._obj, self._name + "._outputData", outputData )
            
            return data
        else:
            #print "returning cached data"
            return outputData[ inputData.index( argsKeysCombined ) ]
    
    
    
    #----------------------------------------------------------------------
    def __repr__(self):
        """Return the function's repr
        """
        #print "running __repr_ in InputBasedCachedMethod"
        objectsRepr = str(self._obj)
        objectsName = objectsRepr.split(' ')[0].split('.')[-1]
        cachedObjectsRepr = ''
        return cachedObjectsRepr


Edit 1: Edited the cache class, now it supports both arguments and keyword arguments, and I didn't delete the lines that has print commands, so you can uncomment the lines to see which one of the methods runs when

Saturday, September 26, 2009

How to Compile PyQt4 for Python 2.6 AMD64 (64 bit) on Windows x64

PyQt 4.5.4 for Python 2.5 amd64
PyQt 4.5.4 for Python 2.6 amd64

Recently I've written an interface for the first time with PyQt4 in Linux for one of our pipeline related scripts. It was working very well under Linux, until I decided to check how it is going to look under Windows x64.

Well, it didn't take too long for me to recognize that there is no PyQt4 for Python 2.5 amd64. So I decided to compile my own. By the way you will see that I started for Python 2.5 but compiled for Python 2.6, it is just because, in a panic mode I've installed Maya 2010 to see if the package I found for PyQt4 for Python 2.6 amd64 for Windows x64 will work under. But no it wasn't ( actually it was, but I didn't know that I should add the path that contains the Qt DLLs to environment path ). So I dived in to compiling PyQt4 for Python2.6 amd64 for Windows x64.

Here you can find the How-To of that compilation...

You need these packages and programs:

MS Visual Studio 2008
Python 2.6 amd64
Qt 4.5.2 SDK for Windows
Sip 4.8.2 Source
PyQt4 4.5.4 Source
Nullsoft scriptable install system

Lets start:

  1. Install Python 2.6.2 amd64:
    • install it to C:\Python2.6
    • if you have already installed it somewhere else, in the rest of this "how-to" use that path instead of C:\Python26

  2. compile sip:
    • download sip-4.8.2.zip
    • unzip sip-4.8.2.zip to C:\sip-4.8.2
    • open up the Visual Studio 2008 x64 Win64 Command Prompt from start menu/programs/etc.
    • run the commands below
    • cd C:\sip-4.8.2
    • C:\Python26\python configure.py -p win32-msvc2008
    • nmake
    • nmake install
    • open the python interpreter and check the module by using:

      from sip import *
      print SIP_VERSION_STR


      if it doesn't give any error messages about a DLL or something, it is installed correctly

  3. compile Qt4:
    • download Qt SDK for Windows
    • install it to C:\Qt\4.5.2 not to 2009.03
    • delete the two tmp files: (they were causing problems in the middle of the compile process, very annoying to start again)
      C:\Qt\4.5.2\qt\src\3rdparty\webkit\WebCore\tmp\moc\{debug,release}_shared/mocinclude.tmp)
    • open up the Visual Studio 2008 x64 Win64 Command Prompt
    • run the commands below
    • cd C:\Qt\4.5.2\qt
    • set QTDIR=C:\Qt\4.5.2\qt
    • set PATH=%PATH%;C:\Qt\4.5.2\bin
    • configure -opensource -platform win32-msvc2008
    • enter "y" for the question
    • nmake ( and go to have a lunch or dinner, seriously, it took 3 hours in my computer, it will be around on yours too )
    • nmake install
    • congratulations you have built Qt4 x64 for Windows x64
      (NOTE 1: you can create a batch file that runs the 'configure' then the 'nmake' and then the 'nmake install' commands, but when you run this batch file wait for 1 seconds to the question in configure step then leave :) )
      (NOTE 2: because we didn't specified a -prefix option in configure, it will compile it over the source directories )

  4. compile PyQt4:
    • download PyQt4 4.5.4 Source
    • unzip the PyQt4 source to C:\PyQt-win-gpl-4.5.4
    • open Visual Studio 2008 x64 Win64 Command Prompt
    • run the commands below
    • set QTDIR=C:\Qt\4.5.2\qt
    • set Path=%PATH%;C:\Qt\4.5.2\qt\bin\
    • cd C:\PyQt-win-gpl-4.5.4
    • C:\Python26\python configure.py -w
    • enter "yes" to the question
    • nmake ( again it takes some time )
    • nmake install
    • now you should be able to use PyQt4, but if there is an error message saying:

      Python 2.6.2 (r262:71605, Apr 14 2009, 22:5+:60) [MSC v.1500 64 bit (AMD64)] on win32
      Type "help", "copyright", "credits" or license" for more information.
      >>> from PyQt4 import QtCore
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      ImportError: DLL load failed: The specified module could not be found
      >>>


      you need to add the folder that contains Qt DLLs to the environment path variables, by using the Control Panel -> System -> Advanced -> Environment Variables

  5. Nullsoft installer to make installable binary package:
    • download and install Nullsoft installers latest version
    • right click C:\PyQt-win-gpl-4.5.4\PyQt.nsi and select "Compile NSIS Script"
      ( unfortunatelly the script gives a lot of errors, you need to copy/paste some files and create folders by your self according to the complains of the compiler )


for Python 2.5, compiling PyQt4 for Python 2.5 x64 is quite similar, you just need to use vs2005 and its x64 command prompt compiler with the nearly the same commands, just replace win32-msvc2008's with win32-msvc2005, that's all...

EDIT 1:

for Python 2.6 version of PyQt4 you need to install Microsoft Visual C++ 2008 SP1 Redistributable Package (x64) also

for Python 2.5 version of PyQt4 Microsoft Visual C++ 2005 SP1 Redistributable Package (x64) also

EDIT 2:

I've compiled the Python 2.5 amd64 version of PyQt4 for Windows x64... Download (the Phonon Multimedia Framework is only supported by python 2.6 an later)

Thursday, September 24, 2009

Python Function Decorators 2: Decorating a Class Method

I think I need to make things a little bit clearer with the code shown in previous post...

The Decoration

Decorating a function enables you to call other code before the original function is called, or you can completely change the functions code. As I've red somewhere it is best equated to preprocessor macros or template libraries in C++.

In my previous post, I've decorated my class methods by adding @CachedMethod at the definition of the class method. This is one of the two ways of defining decorators. When I do that the Python interpreter decorates the unbound function, which means, it is decorated whenever I've imported the module not when I've created the instance object. This leads us to a little but important difference that can easily be neglected, so be careful to not to miss what you intended to do. I mean, when I've first written the CachedMethod class, it was caching the data in the Class not in the instance object. So every instance of that class was trying to use the same cached data, which in my situation was a wrong behaviour, though it is may desirable in some other cases...

By decorating my functions with a class (you can decorate them with functions too), I'm practically turning them in to classes. So instead of being a method of a class, they become a class belonging to another class.

The key to decorate a Class method in a way to be able to reach the instance object is to store the instance object in the __get__ method of the decorator and then use it in the __call__ method.

The order of execution of the CachedMethod classes methods are like that: when you import your module the functions are decorated, and the __init__ of the CachedMethod runs for all of the class methods you have decorated. Then when you create your object nothing happens, but when you call a decorated method, first the __get__ method runs, than the __call__ method. It is a good practice to add print() commands to the decorators method to understand what is going on.

The __get__ method has 3 arguments self, instance and class. Self, as regular, is the CachedMethod instance, instance is the instance of which the decorated function belongs to, and the class is the super that the instance is derived from.

You can change the settings of the arguments of __call__ method, but I think the best settings is a couple of *args, **keys together ( def __call__(self, *args, **keys) ) . So you can get any type of arguments setup passed to your original function and use them in your decorator. Other than this setup you can use the same argument count and order in your original function, but I don't recommend that, because you are restricted to decorate only the methods that has the same types of arguments.

CachedMethod Explained

Here are the brief explanation of what is going on in the methods of CachedMethod class.

__init__ : I store unbound method and the name of the unbound method in class variables, to let my self to call the original function later on.

__get__ : as far as I know, this is the only place that I can get the instance object. I store the instance object in self._obj and check if it already has its attributes set up. If not I create the attributes by using setattr commands

__call__ : I've all the data I need to have, so I do the caching by calling the original function if the self._data is empty or the time delta is bigger than the self._maxTimeDelta, otherwise I return the cached data. To get the data from the instance appropriately I use getattr, and I evaluate the attribute name on the fly by using self._name + '_data' for example.

Thats all... Hope it helps you to understand what is going on. And if not, there are some nice tutorials here and here is a nice function decorator library in Python.org

Thursday, September 17, 2009

Python Function Decorators: Caching a Class Methods Output

I've been writing a class and I've noticed that one of its methods may could create a lot of overhead to our file server when it is used often. And its result was not changing so often. So trying to get all the data over and over again is something I should avoid.

I've decided to create some kind of caching system to overcome this problem. I've changed the function so it was caching its own result, and it was not trying to get the data over and over again before some definite time is passes. It was working very nice. But later on I've noticed several other functions those had to have this functionality.

So I've decided to use a decorator that decorates the functions with that ability. Here is the decorator:
#######################################################################
class CachedMethod(object):
    """caches the result of a class method inside the instance
    """
    
    
    
    #----------------------------------------------------------------------
    def __init__(self, method):
        # record the unbound-method and the name
        #print "running __init__ in CachcedMethod"
        
        if not isinstance( method, property ):
            self._method = method
            self._name = method.__name__
            self._isProperty = False
        else:
            self._method = method.fget
            self._name = method.fget.__name__
            self._isProperty = True
        
        self._obj = None
    
    
    
    #----------------------------------------------------------------------
    def __get__(self, inst, cls):
        """use __get__ to get the instance object
        and create the attributes
        
        if it is  a property call __call__
        """
        #print "running __get__ in CachcedMethod"
        
        self._obj = inst
        
        if not hasattr( self._obj, self._name + "._data"):
            #print "creating the data"
            setattr ( self._obj, self._name + "._data", None )
            setattr ( self._obj, self._name + "._lastQueryTime", 0 )
            setattr ( self._obj, self._name + "._maxTimeDelta", 60 )
            #print "finished creating data"
        
        if self._isProperty:
            return self.__call__()
        else:
            return self
    
    
    
    #----------------------------------------------------------------------
    def __call__(self, *args, **kwargs):
        """
        """
        #print "running __call__ in CachedMethod"
        
        delta = time.time() - getattr( self._obj, self._name + "._lastQueryTime" )
        
        if delta > getattr(self._obj, self._name + "._maxTimeDelta") or getattr(self._obj, self._name + "._data" ) == None:
            # call the function and store the result as a cache
            #print "caching the data"
            data = self._method(self._obj, *args, **kwargs )
            setattr( self._obj, self._name + "._data", data )
            
            # zero the time
            lastQueryTime = time.time()
            setattr( self._obj, self._name + "._lastQueryTime", time.time() )
        #else:
            #print "returning the cached data"
        
        return getattr( self._obj, self._name + "._data" )
    
    
    
    #----------------------------------------------------------------------
    def __repr__(self):
        """Return the function's representation
        """
        objectsRepr = str(self._obj)
        objectsName = objectsRepr.split(' ')[0].split('.')[-1]
        cachedObjectsRepr = ''
        return cachedObjectsRepr


You can use that anywhere you want, but beware that the caching is time dependent, not input dependent.

Saturday, August 8, 2009

After Siggraph 2009

Yesterday was the last day of Siggraph. It was a real mind blowing experience to be a part of it. I was too busy to post something here, but I've got all my notes with me, so I'll arrange them and post something here very soon...

By the way, I've started developing some tools that I've learned in Siggraph, and expect some others too...

Sunday, August 2, 2009

First Night in New Orleans

After 20 hours of journey, I finally got my self in to New Orleans... I will try to blog every interesting detail...

Thursday, July 23, 2009

Siggraph 2009 in New Orleans

In the first 10 days of the August, I'll be in New Orleans to attend Siggraph 2009... I'm very excited because it is my first Siggraph...

Wednesday, July 8, 2009

Switched from Gnome to KDE

Yesterday I switched from Gnome to KDE, now Maya works much much much better, even with composite is on (under KDE, opening the hotbox while composite is on doesn't lock the interface as it does in Gnome, I've red that there is a dead lock issue between Maya and Gnome when composite is on), no sticky keyboard bug under Maya any more and I can adjust the Maya panels so the editors like Attribute editor Hypershade stays on top of the main Maya window until I click to the title bar of the main window... so its cool, its fun again to use Maya under Linux...

Here is the pros of switching to KDE:
  • Maya works flawlessly
  • Using hotbox doesn't hang the whole desktop process
  • Window manager could be adjusted to make the Maya Panels behave as expected
Here is the cons ( for me at least ):
  • A more candy look compared to Gnome ( which may others like )
  • Need to get used to the different tools like kate instade of gedit, konsole instead of the regular terminal etc.
  • KDE and Gnome tools lays side by side if you just install KDE to Ubuntu ( which again may doesn't disturb other people )
  • Finding a tool under the application launcher is more difficult compared to Gnome ( which may I later will get used to )
After installing KDE under Ubuntu, I decided to install a fresh version of Kubuntu, to have the default tools those come with KDE version of Ubuntu (Kubuntu again), this was a very very unnecessary decision, because in Linux world having a fresh install could be get by just using the lovely packet manager and removing the unwanted programs/components/tools...

I wanted to get rid of the extra gnome tools. But now I need to configure all the things from scratch again. I've lost the sound in my laptop (HDX-1080) again, I need to compile 2.6.30 version of the kernel, I think this time I'll wait for the ubuntu version of the kernel to update. I need to install a lot of the programs again, like JEdit, WingIDE, KDevelop etc...

Hopefully, Maya installed very quickly, with the help of this site...

So for now, if nothing bad will happen I suggest to use KDE with Maya...

Monday, June 29, 2009

PoseDeformer for Linux 64 bit

I've compiled the excellent PoseDeformer plug-in from Micheal Commet for Linux 64 bit. You can download the plug-in including the Linux 64 bit version from Djx Blog...

Saturday, June 6, 2009

Production Asset Management (ProdAM) & Shotgun

I found that they call Production Asset Management (ProdAM) System to the systems that we need for our animation studio to track the files, collaborate each other and schedule the tasks.

I've red a lot of books about asset management systems last two months. Most of them were explaining the systems those has been used for the media companies, like systems that works like a librarian for you and find the media (image, video etc.) that has the keywords you've entered, but doesn't essentially track the new versions of it and doesn't have any collaboration or scheduling functionality.

One of the books was "Implementing a Digital Asset Management System". It explains how to choose a right system, and prepare your staff for it. Although, I first thought that it is going to explain how to write one :). What the book offers for an animation studio is simply to use AlienBrain. There are examples of studios who implemented their own solution, like ImageWorks and their TrackIT system.

Because AlienBrain is a high cost solution for our studio, I searched for other alternatives. Eventhough, there is not many alternatives on the market, I found Shotgun. Which is still in development, but there are around 20 studios like Pixar, Framestore, RisingSunPictures, Digital Domain etc. that tried this system and simply loved it. I loved it too. But the cost is not defined yet. So I don't know if we want to spend that money.

What Shotgun offers is, to supply a platform for Scheduling, Tracking, Collaboration and Implementation. It's very powerful, cause you can track any data you need while completing the project. So you have the eagles eye over your project to see how it is going, where are your files, who is dealing with what and many many other things.

Shotgun is based on open source projects like, Ruby, Rails, Appache, PostgreSQL etc. and it is a web based application, so it works on any OS. It uses Python as the API language. Go and watch the tour video on their site.

Shotgun gave a lot of ideas to me and because they are honest enough to show the open source projects that Shotgun is built on, I've got the feeling that I can write a simple version of it.

Saturday, March 7, 2009

Subversion

I started to use SVN to manage my codes.

I feel very ashamed, because I've heard that there are tools to keep track of the data in coders world, but I didn't know that this applications were that much powerful. So, I'm emberassed because I was developing codes for years and I haven't had any information about SVN, CVS, Git, Perfoce etc.. But I think the problem was, the fact that I'm alone. There is nobody to teach me this stuff. Ok there is the internet, but internet is not pushing information to me, before I ask. Allright, I think I can live with that.

I just started a code project in Google Code with the name of oy-maya-scripts. From the project page, you can download the latest scripts and plugins I've written. And because, Google Code supports SVN repositories and I use tortoiseSVN to track my code, it is much more easier to handle the versions between my laptop, my home computer, my workstation at work and the server where the artists are using the scripts. I feel like, I lost some of the weights in my burden. And if you want to contribute you can help developing.

After creating the project, and with the feel of joy, I started to manage my current scripts. I've deleted lots of them, updated the old codes in some old scripts and organized them in a folder dedicated to my scripts only. I seperated the hacked Maya scripts (the scripts that has been written by the alias/autodesk programmers and which I added my own codes inside them to give new functionalities, like adding your own menu commands to dagMenuProc.mel, or to fix the ridiculous image number expression in checkUseFrameExtension.mel) in another folder. I standardized the format of the heading of the code files etc.. I've even found an old script that I've written 2 years ago, which actually does the same thing I need to code for an upcomming project.

SVN or these versioning applications are absolutly usefull tools. I'm curious about how I survived this far without them.

Thursday, February 12, 2009

Brad Friedman's Blog

While searching for a way to have the auto-complation in WingIDE I came across this wonderfull blog of Brad Friedman. I've red his entry about his asset management system which he calls "GlobalStorage" where at the end of this entry I was almost going to cry in bliss :)

I was working for an animation studio last year. Which has around 20 artists in total. I was the only Technical Director dealing with everything considered technical. I had a lot of problems with the file structure we were using (actually we didn't have one).

Even with this little group of artists, the file names and paths gets confused without using a management for the files. So I couldn't find the latest versions, files were named like final_anim.mb or final_RealFinal_anim.mb. Being the villain and dictating didn't solve anyting.

I've tried to organize by creating directories with meaningful names for every phase of the job, and I've adjusted the workspace.mel so maya can understand the structure. Again it didn't solve anything. I needed a little time to write a proper asset management or at least something that manages the files. New jobs were comming constantly, I didn't have time. The pressure was increasing, following the files was getting harder and harder. So I was crushed under that pressure on my shoulders and I resigned from my job last year ( there were other things too).

When I started working for my current job, I asked them how are they managing their files, they explained that they were using a very simple system for XSI to set the file name and path. They had a little Java script which manages the creation of project folders and adding shots to the lists.

I've re-written the code from scratch with C# and MEL. I've made the code much more flexible than before. So in Maya when an artists wants to save his/her file, he uses my save as script (oySaveAs). It is a simple form that users must fill the fileds. There are fileds for project name, scene name, shot number, shot type, revision and version numbers, user name initials, so the scripts decides the file name and path. The fields are filled automatically after the first usage. So if you are doing an animation for a job named JEMBEY, for the scene SEVGILILER_GUNU and shot 012, the file path and name becomes :

M:/JOBS/JEMBEY/MAYA/SEVGILILER_GUNU/ANIMATIONS/SH012/SH012_ANIMATION_r00_v001_oy.mb

or if you are doing a model of a character named KIZ than the file path and name becames:

M:/JOBS/JEMBEY/MAYA/SEVGILILER_GUNU/MODELS/KIZ/KIZ_MODEL_r00_v011_oy.mb

of course, it is not a complete asset management system, or at least it is managing from one side, by just putting the files in a correct place with a correct name.

Brad's system is something huge really huge when compared to my little tiny scripts. He is using Subversion as the base system and he has written a lot of code over it with Python to get the nice features of his management system. Go and read his entry about GlobalStorage.

Wednesday, February 11, 2009

WingIDE with Maya Python

I'm searching a way to have auto-completion in WingIDE for MayaPhytonAPI...

Saturday, January 19, 2008

Blog or not to blog

I sent my last blog, 1 year ago, been so long , infact I have a real notebook which I use as a blogger, writing blogs that only I’ll read is much more easier than writing blogs that will be read by millions of people, maybe thats why I didn’t sent any entries.

However, the technical discoveries, the results of my tests, new script and plugin ideas that I wrote on this notebook could be very helpful to people who try to learn Maya API and MEL scripting.

Thereafter, whenever I have time I’ll send new entries to my blog…

And I’m little bit confused about the language of the blog, I don’t want to write it only in Turkish, and writing it in English beside Turkish would be time consuming, writing it only in English is the best idea I think, however it wouldn’t have any effect on Turkish source count on the net…

Monday, January 8, 2007

Rivet (continues)


I finally did what I thought would be the final thing to do: I edited the pointOnMeshInfo.mll and included the calculation of tangentU. Although it uses 2 nodes, it doesn't works faster than Bazhutkin's version, I don't know why. So it is your choice.

Here you can downlaod the plug-in and mel scripts:

rivet_for_Maya7.0.zip


To make it faster, I have some ideas. The first thing could be done is to eliminate the need of an aimConstraint node by directly calculating the rotational values within the node itself. The second one could be calculating all the rivets' positions and rotations at once within a single node.

I thing I will give a break to this rivet problem, I'll work on this when we need this on our animation studio...

Sunday, January 7, 2007

CGIndia

visit cgindia.blogspot.com daily, I do so... 

Saturday, January 6, 2007

Rivet

Allright, now start with some real posts:

the recent two days I searched for a way to do the rivet thing using a method other than what Michael Bazhutkin used (www.geocities.com/bazhutkin). I found a way that use only 3 nodes where Bazhutkin's version use 5 nodes (including aimConstraint node), I wrote the script and it was working very well, but it was 2 times slower than Bazhutkin's version.

What I did was, I used two pointOnMeshInfo node which gives a position and normal vector, and an aimConstraint node. The first pointOnMeshInfo node calculates the position and normal the second one is just used for to get the position that aimConstraint will try to aim.

The problem is that if I used 2 pointOnMeshInfo nodes just to see how fast that they calculate, it is 2 times faster than Bazhutkin's, but the locator doesn't rotates of course, if I use 1 pointOnMeshInfo node and one aimConstraint node it is again 2 times faster, but the locator doesn't points the right point of course...

It gets slower when I try to use three of them. I will try to find a way to use only one pointOnMeshInfo and one aimConstraint nodes.