Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Wednesday, January 15, 2025

Blender - AI-T - NVIDIA - 2025

I praised the lord that I could participate at the first time on the Blender conference. I was really amazed that creative community is so creative, innovative, open-minded (and unsustainable (free Coca Cola wtf?)...but it is a different topic).

If you ever wanted to understand color management, my advice is to give up :) and just follow the best practices what Jacob Holiday showed us, for eg. Really, really powerful presentation.

If somehow you are not fulfilled after this ↑, check this: the Bible (of Color Management) aka Cinematic Color. 

Also worth to mention MagnumVD. This youngster do stuff, and I mean it.




My presentation was a little bit different and it is only for online communities.


But what about NVIDIA and AI-T (artificial intelligence/information technology). I think the misconception about AI is that these stuff is for Artist. Not really. Artist enjoys creating stuff. If you want to skip the process you rather want to be startup or real estate investor. But there is this mantra: "be more and more and more efficient" but those are rather technical topics than artistic.
To contradict myself being an artist means we have craft (aka technical) skills to use tools like paint and brushes for painting. We get skills of using Blender and so on. So these are also technical topics. Since we use software (at least computer artists) that written in programming language leveraging scientific knowledge and research it really essential to at least have a grasp about the technology and science behind the tools what we are using as an artist. As the great painters hundreds of years ago, they were the masters of utilizing the chemistry of the paints and the canvas fabric and so on.

So that's where can be a major shift, or will emerge a new generation of artist who mastering the AI trainings to train the best models to create images, visuals, videos, sound, substance what cannot be done before. 

I really feel there is an interesting position of NVIDIA in that process of advancing AI technologies. Because they belong with us. NVIDIA has significantly advanced computer graphics over the past decades, and they recognize the enormous business potential in this AI field (just look at their stock market performance). However, this rapid development also challenges the value and role of being an artist in today's world.




Francesco Siddi also touched this topic on BCON however it is not really a thing.


Here we go 2025 (not to forget the energy crisis crashes the climate...turn off your computer and give up crypto-mining)




Thursday, November 17, 2022

Pipeline Movies

The pipeline is always with us. Even if we don't think about it, because it is different from studio to studio, it is exciting to see how they deal with it.

Old but gold (actually, Rhythm & Hues no longer exists, which is the most depressing story of all time in the industry).

Rhythm & Hues - A Framework for Global Visual Effects Production Pipelines - SIGGRAPH 2014 from Murali Anagani on Vimeo.


Since the ShotGun Software has been renamed to ShotGrid, which is a more PC name for a production tracking system :)

Tony Barbieri and Don Parker; The Shotgun Pipeline at PSYOP from Autodesk Media and Entertainment on Vimeo.


The best pipeline presentation(s) of all time (still ancient which is a bit of a sign that nowadays there are less intersting talk on that field).


Not soo long time ago there was a discussion hosted by Side Effects Software at Siggraph.


Or I'm just getting old and only have good memories from the far past—cinesite's presentation about generalizing pipeline and implementing fTrack.



Last but not least: if we are talking about the pipeline, it's unavoidable to talk about Katana. The exciting part is that people may think that Katana is a lighting & rendering tool. Actually, it is a pipeline tool because of the nature of rendering. If you want to render anything, you must create a complex system to flow the data from DCCs (digital content creation tools) to the render engine. That's where Katana comes in. So here is a brilliant presentation about Katana deployment.


Friday, May 27, 2016

Nuke - Print out AppendClip Inputs

AppendClip node is useful for anything like viewing a bunch of shots after each other. I used it to check out different versions of FumeFX simulations. Only one thing I had to find out: how to print the current version (version of the file sequence) of the effect out to the screen. Using a Text node we could utilize python commands within the message field. So the node graph is something like this:


And the python command (it called from TCL):


[python {nuke.thisNode().metadata()['input/filename'].split('/')[-1]}]

I don't know much about TCL but I could figure it out how it would look like in TCL syntax:

[lindex [split [metadata input/filename] {/}] end] 


It reads the node's metadata which is passed through by the current read node. The metadata holds the input/filename key and that is what we are looking for. nuke.thisNode is the node where the comman is called (the Text node in this case). Further information is here. In TCL it seems there is a basic metadata command.

Tuesday, February 9, 2016

Nuke - Calling python from TCL - File Name To Label

So trivial but always forgotten (by me). Rigth now I write it down for the eternity.

The most common situation when we might want to call python from TCL is using the label field on the given node's Node tab. If we put some text here like "maki"

 
it will appear below the node's name in the node graph.


If we use bracket "[ ]" to delimit the text it is interpreted as TCL command until it is valid command (otherwise it will be only text). So we can put something like this:

focal: [value focal]

It would look like this:


To call python we can to use the following syntax:

[python {python commands}]

To output the file name of the camera we can use the following expression:

[python {nuke.thisNode()['file'].value().split("/")[-1]}]

It would look like this: 


Thursday, June 11, 2015

Maya - Node Types - Filter Types

How to list all the lambert shaders in maya?
Well, if we use the MEL or pyhton command ls -type "lambert" we get more than just lambert shaders (if there are others in the scene). The reason is that the lambert shader has a type name which is the type for eg. blinn and phong are inherited from. The class hierarchy or inheritance diagram looks like this.


We can get this from the maya API documentation but we can query via MEL or python commands.

The following line gives us the inheritance diagram of  "blinn1" shader as a list:

 cmds.nodeType("blinn1", inherited = 1)  
 # Result: [u'shadingDependNode', u'lambert', u'reflect', u'blinn'] #   

As we can see the items are similar but not the same. That is why because MEL and python scripts not work with C++ API names. If we look up blinn  node from the nodes list of the technical documentation area we can see the parents field:


If we click on reflect we get the node to get the description of that node we can see the relfect node's partent is the lambert.

So we can really search node types or "supertypes". We can imagine these nodes as part of a set. Maya  ls command and other commands with type flag can use these types. So for eg. we can list all the shape nodes in the scene by entering the following line:

 cmds.ls(type = "shape")  

Or we can filter all the geometry type shapes, like curves, nurbs surfaces, meshes:

 cmds.ls(type = "geometryShape")  

So answering the first question: we can filter lambert shaders if we list lambert type with ls than check the exact type with nodeType command.

 lambertTypeMaterialList = cmds.ls(type = "lambert")  
 lambertMaterialList = []  
 for item in lambertTypeMaterialList:  
     if cmds.nodeType(item) == "lambert":  
         lambertMaterialList.append(item)  
 # Result: [u'lambert1', u'lambert2'] #   


With python set we can achieve useful functions easily. I wrote a function to check two or more objects' common type. I hope it works well.


 def GetCommonClass(SelectedNodeList):  
     '''  
     == DESCRIPTION ==  
     Get the common type of the passed object list which is the first item in the inheritance diagram.  
     For eg. if we test a directionalLight and a nurbsCurve type nodes together the inheritance diagram are like this:  
     [u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'deformableShape', u'controlPoint', u'curveShape', u'nurbsCurve']  
     [u'containerBase', u'entity', u'dagNode', u'shape', u'light', u'renderLight', u'nonAmbientLightShapeNode', u'nonExtendedLightShapeNode', u'directionalLight']  
     And we can see the first common type is the 'shape'.  
     == INPUT ARGUMENTS ==  
     + list - SelectedNodeList - Maya node list  
     +  
     == RETURN ==  
     string - the first common type   
     == DEPENDENCIES ==  
     - maya.cmds  
     -  
     '''  
     if SelectedNodeList:  
         nodeTypeList = []  
         nodeTypeSet = set()  
         for item in SelectedNodeList:  
             nodeTypeList = cmds.nodeType(item, inherited = 1)  
             print nodeTypeList  
             if len(nodeTypeSet) != 0:  
                 nodeTypeSet.intersection_update(set(nodeTypeList))  
                 if len(nodeTypeSet) == 0:  
                     print "There is no common type within selection."  
                     return None  
             else:  
                 nodeTypeSet.update(set(nodeTypeList))  
         commonTypeIndexList = []  
         for commonType in nodeTypeSet:  
             commonTypeIndexList.append(nodeTypeList.index(commonType))  
         firstCommonType = nodeTypeList[sorted(commonTypeIndexList)[-1]]  
         return firstCommonType  
     else:  
         return None  

Thursday, February 19, 2015

Maya (2013+) - imagePlane issue

I had trouble with imagePlane in maya 2015. As far as I know it is changed around maya 2013. ImagePlane now has a transform node so it looks like a standard object. You can create it from the menu: Create / Free Image Plane.


The strange thing is that when it is attached to a camera. It looks like a hierarchy (see below)


but it can't be unparent or reparent. So there is a special connection. In nodeEditor it also looks like a typical hierarchy where the transform node does not have any connection.


Only thing which can refer to some special condition is found in the scriptEditor when the imagePlane is selected:

select -r CameraShape->imagePlane1 ;

I experienced this syntax with positionMarkers. Actually I wrote about it before.

That is how I find out there is a term of underworld nodes in maya. You can read about it here or a more here. Consider underworld node as a component like a NURBS CV and it will explain why it can't be unparented for eg.

So...we can create an imagePlane with MEL command (since maya 2013) like this:

imagePlane -name "myImagePlane" -camera "CameraShape";

And we can redirect" an existing imagePlane to another camera with the edit flag:

imagePlane -edit -camera "NewCameraShape" "myImagePlane";

I found the easiest way to get the imagePlane from the camera is to call this:

listRelatives -allDescendents "cameraShape"

Friday, August 1, 2014

Maya Functions - Removing Plug-in Nodes

To disable or unload a plug-in in maya could be tricky. I had situations when a plug-in could not be unload even if I pushed the 'Force' button on the poping window in Plug-In Manager because nodes of a certain plug-in was in use.


It seems maya can't always (or never) delete nodes that are in use. I had situations when maya crashed when I was loading a scene file which contained unknown nodes (unknown plug-in nodes). Actually I had to find out that the reason of the crashing is that a certain plug-in was not installed on my computer. Scene with Arnold nodes can produce crash when you want to load into a maya without installed Arnold plug-in.
So there is a need to delete plug-in nodes manually...or with a python script.

The main command is:

 cmds.pluginInfo("Mayatomr", q = 1, dependNode = 1)  

With argument "Mayatomr" it will list all the Mental Ray plug-in nodes. Or "mtoa" would list all Arnold specific nodes. Of course even if the plug-in is loaded this command returns something only if there is at least one node of that plug-in in the current maya scene.

Here is a function for removing plug-in specific nodes:

 def RemovePluginNodes(PlugIn = "mtoa", Verbose = 1):  
     '''  
     DESCRIPTION  
     Remove nodes of the given plug-in.  
     INPUT ARGUMENTS  
     - string - PlugIn - Name of the plug-in. You can check the exact (maya) name of the plug-in in the Maya Plug-in Manager. 
                         For eg.: Mental Ray plugin file: Mayatomr.mll -> "Mayatomr"  
     - int - Verbose - provide extra information about the process  
     RETURN  
     None  
     '''  
     plugInNodeTypeList = cmds.pluginInfo(PlugIn, q = 1, dependNode = 1)  
     for plugInNodeType in plugInNodeTypeList :  
         existingPlugInNodeList = cmds.ls(type = plugInNodeType)  
         if existingPlugInNodeList:  
             cmds.delete(existingPlugInNodeList)  
             if Verbose:  
                 print "Deleted nodes:\t%s" % existingPlugInNodeList  

I haven't tested extensively so give it a try and let me know your experience.

Friday, February 28, 2014

Maya Tools - Locator size by scale - Write a function

So, we saw there was a simple 4 lines script to adjust locator size by scale.
How to make a so called tool?
I have no idea whether there is a scientific approach of that. I know about writing a specification. As a matter of fact I found a good article about that: Painless Functional Specification
I simply skipped the first chapter because I knew that is important so I didn't need a tale about that :)

But before I even knew about specification I usually thought as a user because I stared my "career" as an artist not a TD.
In this case this tool  should be only one click solution: Set Locator Scale By Size. To make it clear it is not for locator type object but cameras and lights. There shouldn't have been any other things just one button to click so we can move on to technical specification.

First of all we should write a function:

 def LocatorSizeByScale(Selection):  
     for item in Selection:  
         scaleVal = cmds.getAttr(item + ".s")[0][0]   
         cmds.setAttr(item + ".s", 1, 1, 1)   
         cmds.setAttr(cmds.listRelatives(item, shapes = 1)[0] + ".locatorScale", scaleVal)  

The argument should be a Selection. In maya ls command results a list no matter whether it is one or more object so the Selection has to be a list (array). With for cycle it works more than just one object. So we can run the function like this:

 LocatorSizeByScale(cmds.ls(sl = 1))

But as I wrote before there could be a lot of error situation. I'm a visual thinker. I don't make every time flowcharts but for the sake of this demonstration I'm going through the whole process of visual design. I'm a self-taught programmer and this is my practice not a scientific approach.

First I made a sketch of a flowchart.



It took around 5 minutes and another 5 minutes to verify and add notes. After that I could start coding. I had a clear picture how it would work. Okay but I don't expect reading that from anybody. I made a better picture for this article.





This flowchart shows everything what we need. If we can draw a flowchart like this we have a clear picture how the function is going to work. So the coding is just an execution of the plan.

The result code:

 def LocatorSizeByScale(Selection):  
     '''  
     DESCRIPTION  
     Scaling camera for eg. can cause problems (Z-Depth pass can be wrong for eg.). So scale value should be transfered to the locatorScale attribute.  
     If the object (the selected node's first shape node) has locatorScale attr it will be adjusted by the transform node scale.  
     INPUT ARGUMENTS  
     list - Selection - Selected nodes  
     RETURN  
     None  
     DEPENDENCIES  
     maya.cmds  
     maya.mel  
     '''  
     if Selection:  
         for item in Selection:  
             if cmds.nodeType(item) == "transform":  
                 # Only checks scaleX attribute. That means non-uniform scale not handled.  
                 scaleXVal = cmds.getAttr(item + ".scale")[0][0]  
                 if scaleXVal != 1:  
                     # Only the first shape node considered  
                     shapeNode = cmds.listRelatives(item, shapes = 1)[0]  
                     if shapeNode:  
                         if mel.eval("attributeExists \"locatorScale\" " + shapeNode):  
                             locatorScaleVal = cmds.getAttr(shapeNode + ".locatorScale")  
                             cmds.setAttr(item + ".scale", 1, 1, 1)   
                             cmds.setAttr(shapeNode + ".locatorScale", locatorScaleVal * scaleXVal)  
                         else:  
                             raise StandardError("There is no locatorScale attribute to adjust.")  
                     else:  
                         raise StandardError("There is no shape node.")  
                 else:  
                     print "Default scale value. Skipped."  
             else:  
                 raise StandardError("Only works for transform selection.")  
     else:  
         raise StandardError("There is no selection.")  
 
Further development
Better error handling in connection with selection and selection types
Non-uniform scaled object
Option to warn non-uniform scaled object
Option to warn already set locatorScale value

We will continue...

Tuesday, July 23, 2013

Maya Tools - Locator size by scale

In Maya it can cause a problem if we scale objects like camera and lights. For eg. camera imagePlane.depth attribute is affected by scale value. I had a situation when render output was a empty black image because camera (transform node) was scaled. But of course it is much easier to scale than look up the locatorScale attribute on cameraShape for instance.

So here is an easy primitive python script to adjust locatorScale based on transform node scale.

 selectedObject = cmds.ls(sl = 1)[0]  
 scaleVal = cmds.getAttr(selectedObject + ".s")[0][0]  
 cmds.setAttr(selectedObject + ".s", 1, 1, 1)  
 cmds.setAttr(cmds.listRelatives(selectedObject, shapes = 1)[0] + ".locatorScale", scaleVal)  

Okay, it can produce tons of errors if you don't use it properly. I'm going to write a function (a real tool) to check errors. I guess it will be at least 40 lines instead of 4...so the post title was kind of a bluff.
Recently I have been thinking a lot about how to simplify error handling.