Jan 12 2012

Studio Level Managment Of Scripts and Tools in Maya

Today i started to do some online research on what are the current practice for script/and shelf deployment in maya.
the studio I’m currently working for is not a “Maya” house, but we’re getting to the point where often writing tools to convert scenes animated in maya, to something we can use in max. being that this is a somewhat esoteric topic i did not expect that my internet search would return much, but to my surprise i found this article by fellow TD Jonas Avrin.

he really does a great job at introducing the concept of the userSetup.mel as a ways of deploying his personal script from gig to gig.

which seems to me would also make a great starting point along with the mayaEnv.mel to starting the journey into the full time time management of Maya at the studio level.

this might not be anything new to maya TD’s but it was very informative to me :)

cheers!

http://www.jonasavrin.com/2010/08/15/maya-env-configuration-of-variables-using-usersetup-mel/

http://www.jonasavrin.com/2011/02/18/maya-env-configuration-of-variables-using-usersetup-mel-and-usersetup-py/


Jan 10 2012

Singular Value Decomposition (SVD) and object oriented Bounding Boxes

So a continuation of my previous post.. while trying to figure out how to implement SVD (Singular Value Decomposition) algorithm to figure out the best possible aligned bounding box for a set of points.
my friend Ghram Fyffe pointed my to a python library called “numpy” which has great SVD functions that is incredibly easy to use :)
seance 3ds max does not support python, i decided i would write the python code to read all the vertex information from a text file, and then overwrite the content of that text file with the resulting alignment matrix.
this method should be eazy to implement into any amp even if it does not have native python support.

i hope this code is helpful to you some one. here it is!

'''
PCA optimized axis generator generator (now threaded)

By Carlos Anguiano
this script will process a text file with point data
and generate and optimized object orient bounding box for the point set
c:\python26_64\python.exe
"C:\svnTools\trunk\S2\exchange\software\managed\pythonScripts\PCAOptOOBB\PCAOptOBB.py"
"C:\Users\SCANLI~2\AppData\Local\Temp\PointCloudData
'''
import time
import threading
import sys
import string
import numpy

import os
#this argument feed the script the folder which to parse for pointCloud data files
#PCFld = sys.argv[1]
PCFld = 'C:\Users\SCANLI~2\AppData\Local\Temp\PointCloudData'
maxThreads=8

def OptmizedTransformAxisFromPointCloadFile (infile):
     lines = open(infile,'r').readlines()
     lCount = len(lines)
     lCount
     vAr = ""
     for i in range(lCount):
         l = lines[i]
         vector = (l.rstrip())
         vAr += vector

         if i != (lCount-1):
             vAr += ";"
     #once you turn the file content into a string list (look up charArrays) the magic happens
     m = numpy.matrix(vAr)
     USV = numpy.linalg.svd(m)
     return USV[2]

def formatData(data):
     lines = []
     for i in range(3):
         A = numpy.asarray(data[i])
         x = A[0][0]
         y = A[0][1]
         z = A[0][2]
         s = "["+str(x)+","+str(y)+","+str(z)+"]\n"
         lines.append(s)
     return lines

class OptTransAxisFromPCF (threading.Thread):
     def __init__(self,filename):
         self.filename = filename
         threading.Thread.__init__(self)

     def run(self):
         filename = self.filename
         axisData = OptmizedTransformAxisFromPointCloadFile(filename)
         lines = formatData(axisData)
         f = open(filename,'w')
         f.writelines(lines)

def OptmizedTAxFromPCldFiles (Fldr):
     pcFiles = os.listdir(Fldr)
     if len(pcFiles) == 0:
         print "no files to process in this folder"
         return false

     for f in pcFiles:
         while(threading.activeCount()>=(maxThreads + 1)):
             print 'Waiting for a thread to free up...'
             time.sleep(.25)
         absF = Fldr+"\\"+f
         OptTransAxisFromPCF(absF).start()
     while(threading.activeCount() != 1):
         time.sleep(.25)

Optmiz1edTAxFromPCldFiles(PCFld)

Oct 11 2011

Object oriented minimum bounding box resources

I might put together a lib for auto creating low ress standing geometry for models..
Here’s some interesting stuff on creating an aligned bounding box that’s independent of the transform orientation of object it represents :)

http://en.wikipedia.org/wiki/Minimum_bounding_box_algorithms


Oct 6 2011

C# .net custom forms

I’ve been playing around with the idea of learning c# so I can write custom .net widget..
Here’s a promising link with what seems to be a cool intro :)

http://www.akadia.com/services/dotnet_user_controls.html


Sep 15 2011

My Sql Dotnet and maxscript…

Today i ran in to a great snippet that shows how to interact with a mysql server via maxscript…

i have had a chance to try it out but it looks very promesing.

the snippet was taken from “Ofer Zelichover” site (http://www.oferz.com)

check it out if you have a chance…

 

(
  /*
  -- This is a small tutorial on how to use the MySQL Connector to query a MySQL database.
  -- This tutorial assumes you have a MySQL server already set-up, that you installed the
  -- MySQL Connector (available at MySQL website) and that you have basic knowledge of SQL.
  -- I will create a wrapper for easier usage in the near future.
  -- Enjoy. -- Ofer Zelichover (www.oferz.com) 2008-03-08
  -- First load the dotNet assembly. Make sure the string points to the place where you installed
  -- the MySQL Connector DLL file.
  */
  dotNet.loadAssembly "C:\\Program Files\\MySQL\\mysql-connector\\bin\\MySql.Data.dll" 

  /*-- Now define the connection parameters.*/
  local host = "localhost" -- The name of the MySQL server
  local database = "test"-- The name of the database to use
  local user = "test" -- The user name to use
  local password = "test"-- The password to use
  /*-- And build the connection string */
  local connectionString = "Database=" + database + ";Data Source=" + host + ";User Id=" + user + ";Password=" + password
  /*-- Create a connection object */
  local DBConnection = dotNetObject "MySql.Data.MySqlClient.MySqlConnection"
  /*-- Set the connection parameters using the connection string. */
  DBConnection.ConnectionString = connectionString
  /*-- Open the DB connection */
  DBConnection.open()
  /*-- Print the connection status: 1 - connected; 0 - not connected. */
  print DBConnection.state.value__

  /*-- Add a 2 new rows */
  local cmdObject = DBConnection.CreateCommand() cmdObject.commandText = "INSERT INTO test_table (`name`, `phone`) VALUES ('another name','1234567890'), ('yet another name','2468101214')"
  local readerObject = cmdObject.ExecuteReader() -- Print the number of affected rows format "Added % new rows\n"
  readerObject.RecordsAffected readerObject.close()
  /*-- Change the value of the the second row in the table: */
  local cmdObject = DBConnection.CreateCommand()
  cmdObject.commandText = "UPDATE test_table tt SET tt.name='modified name', tt.phone=78978979 WHERE tt.id=2" local
  readerObject = cmdObject.ExecuteReader()
  /*-- Print the number of affected rows*/
  format "Modified % row(s)\n"
  readerObject.RecordsAffected readerObject.close() -- Query the database:
  /*-- First create a command object. This object is used to send the query to the database.*/
  local cmdObject = DBConnection.CreateCommand()
  /*-- Define the SQL query you wish to execute: */
  cmdObject.commandText = "SELECT * FROM test_table tt"
  /*-- Then execute the command to create a reader object. local*/
  readerObject = cmdObject.ExecuteReader()
  /*-- Print the field names from the result: */
  for i = 0 to (readerObject.FieldCount - 1) do print (readerObject.getName i)
  /*
  -- Print the results:
  -- The readerObject.read() method advances to the next record in the reader object.
  */
  while readerObject.read() do
  (
     local record = readerObject.item
     /*-- Now print the record values. This assumes you know the field names: */
     format "%\t%\t%\n" record["id"] record["name"] record["phone"]
     /*-- Another option, if you don't want to use explicit field names:*/
     for i = 0 to (readerObject.FieldCount - 1) do format "%\t" record[i] format "\n" )
     /*-- Close the reader object*/
     readerObject.close()
     /*-- Close the connection*/
     DBConnection.close()
  )

Sep 14 2011

Another great link about using quaternian rotation in rigging

http://www.cuneytozdas.com/tutorials/maxscript/


Sep 14 2011

This guy is really smart!

Check out his work!

http://joleanes.com/tutorials/flippingless/flippingless_01.php


Aug 31 2011

Intersting work worth looking into

http://www.softimageblog.com/archives/108

http://www.softimageblog.com/archives/109

http://www.softimageblog.com/archives/33

http://research.animationsinstitut.de/22.0.html

http://wiki.animationsinstitut.de/doku.php?id=facialanimationtoolset:sticky


Jul 21 2011

Object oriented UIs in maxscript

(This is a work in progress so i hope that my poorly written ramblings are somewhat helpful even if they are a pain to read)
While maxscript has done a great job integrating the concept of object oriented programing through the “struc” constructor. Implementing rollouts and Ui elements that are fully embedded into their parent objects is not as straight forward as one would hope.
Not to long ago a good friend and coworker of mine, Lukas Lepicovsky, showed me a great way to embed the parent struct into almost any Ui element (via a local variable).
The method involves trading the “on open” event handler of a rollout for a initialization (fn init self) function that can be ran after the dialog has been opened, allowing to store the struct into the rollout, via a local variable (local self).

Let’s take a look at a sample struct with rollout function

Struct mytool
(
    /*rollout varible*/
     Ro,
    /*rollut creator function*/
    fn Ui =
    (
        Rollout ro01 "myrollout"
        (
            Button btn1
        )
        Ro01
    ),
    /*ui execution function*/
    Fn run =
    (
        Ro = Ui()
        Createdialog Ro
    )
)
/*make an instance of the struct*/
Mtool = myTool()
Mtool.run() /*--run the ui*/

In this example the code creates our object and runs our Ui creation function..
This method allows to interact with the rollout trough the struct instances (Mtool) but the rollout is unaware of the object instance.
If we wanted to use functions or access variables embedded in the struct we would have to do it by hard coding the global variable mTool in our rollout code, but we would be unable of having multiple instances of this same Ui open with out sharing the same object instance (bummer :( )

In order to make our struct and Ui fully intance-able. we will introduce the concept of self (a variable holding a link to the struct that created the Ui).
Here what this implementation looks like….

Struct mytool
(
    Self, /*--self varible will hold a link to the instance*/
    Ro, /*-- will hold value*/
    TestValue = 0, /*-- this is a test value you will you to test the live link between the object instance and the ui*/
    fn Ui = /*--create rollout function*/
    (
        Rollout ro01 "myrollout"
        (
            Local self /*--this will hold a link to our struct instance*/
            Button btn1 "go"
            Fn init pself = self = pself /*--this functions ran after dialog creation will embed a link to the instanced function into the local varialbe self of the rollout*/
            On btn1 pressed do print self.TestValue /*--print the testValue in the instanced struct*/
        )
        Ro01
    ),
    Fn run =
    (
        Ro = Ui() /*--make rollout*/
        Createdialog Ro
        Ro.init self /*--embed instanced struct into rollout*/
    )
)
Mtool = myTool() /*--create instance*/
Mtool.self = Mtool /*--make instance aware of it's self*/
Mtool.run() /*--run ui*/

So one might ask… why is this better? or why should i go through the trouble of making my ui aware of the object instance it created it?
well this while this type of aprouch might be over kill for simple tools, it facilitates the programing of tools that will be used in a way which will require them to be open multiple times but have different settings.

a good implementation of this might be ui for displaying all the keyframable objects of a character rigg.
in order to write this tool in a way that you can have multiple instances of the ui open pointing a different character riggs the ui needs to be able to store all it’s data in a nice package way that imune to changes by any other script in the application environment.
that’s where the struct comes :) and by letting the the ui refrence it’s own struct this programing task becomes much esier…

here’s a simple example of this pardigm using our struct example

/*--first instance*/
Mtool = myTool()
Mtool.self = Mtool
Mtool.run()
Mtool.testValue = 10

/*--second instance*/
Mtool = myTool()
Mtool.self = Mtool
Mtool.run()
Mtool.testValue = 3

this code should open two instances of the same ui… but pressing the go button will print different values based on the instance :)


Jul 21 2011

Maintenance :(

I’m experimenting with wordpress to try and speed it up some…
So don’t freak out if the site is momentarily down our the appearance has changed :)
Wish me luck!