Sunday, May 16, 2010

Python and threading

Python and threading

The Python language comes with built-in threading support. This functionality is available within Maya, but there are some significant constraints that Python developers need to be aware of.

Maya API and Maya Command architectures are not thread-safe. Maya commands throw an exception if they are called outside the main thread, and use of the OpenMaya API from threads other than the main one has unforeseen side effects.

Despite restrictions, there are many potential uses for threading in Python within the context of Maya; for example, spawning a thread to watch a socket for input. To make the use of Python threads more practical, we have provided a way for other threads to execute code in the main thread and wait upon the result.

The maya.utils.executeInMainThreadWithResult() function takes either a string containing Python code or a Python callable object such as a function. In the latter case, executeInMainThreadWithResult() also accepts both regular and keyword arguments that are passed on to the callable object when it is run.

The script or callable object is executed in the main thread during the next idle event. The thread calling executeInMainThreadWithResult() blocks until the main thread becomes idle and runs the code. Once the main thread is done executing the code, executeInMainThreadWithResult() returns the result. If executeInMainThreadWithResult() is called from the main thread, then it simply runs the code immediately and returns the result.

Because idle events are being used to implement executeInMainThreadWithResult(), it is not available in batch mode.

import maya.utils import maya.cmds
def doSphere( radius ):
 maya.cmds.sphere( radius=radius )
maya.utils.executeInMainThreadWithResult( doSphere, 5.0 )

maya.utils

The maya.utils package is where utility routines that are not specific to either the API or Commands are stored. This module will likely expand in future versions.

Currently, the maya.utils package contains three routines relevant to threading (see the previous section for details on executeInMainThreadWithResult).

There are two other routines in maya.utils:

  • maya.utils.processIdleEvents(). It is mostly useful for testing: it forces the processing of any queued up idle events.
  • maya.utils.executeDeferred().

    (Similar to maya.utils.executeInMainThreadWithResult() except that it does not wait for the return value.) It delays the execution of the given script or function until Maya is idle. This function runs code using the idle event loop. This means that the main thread must become idle before this Python code is executed.

    There are two different ways to call this function. The first is to supply a single string argument which contains the Python code to execute. In that case the code is interpreted. The second way to call this routine is to pass it a callable object. When that is the case, then the remaining regular arguments and keyword arguments are passed to the callable object.

Python in Maya

Python in Maya

Autodesk Maya supports the use of Python-style scripting wherever you used to use MEL commands. The implementation of Python scripting in Maya provides the same access to native Maya commands as is provided through MEL. That is, all of the built-in Maya commands, such as sphere, ls, and so on, are accessible through Python.

Commands that are written as MEL scripts—which are actually MEL global procedures (procs)—are accessible using a call to access MEL (maya.mel.eval). For more information, see MEL/Python communication.

NoteThere are certain MEL built-ins that are not available in Python, though they generally have Python counterparts.These include math functions (abs, sin, cos, ...) and string functions (match, gmatch, tokenize...). (The set of MEL built-in functions can be considered the MEL runtime library.)

Python comes with a wide variety of standard modules that provide similar functionality. Refer to Python documentation for information on what is available and how to use these functions in your Python scripts.

Python Command Reference

There is a Python command reference similar to the MEL command reference. For details on all Python commands, refer to the Python command reference documentation in Maya Help.

You can access the help by selecting Help > Python Command Referenceor open the Maya Help ( Help > Maya Help), and when the Help appears, click CommandsPython at the bottom of the navigation frame.

Version

Maya installs Python with your Maya installation. Maya uses Python version 2.5.1 on all supported platforms. The standalone Python shell for Maya is named mayapy.exe on Windows and mayapy on Linux and Mac OS X.

External resources

For information about getting started with Python, including reference material and resources, see:

Initializing the Maya Environment in and for Python

Maya runs any Python commands in the userSetup.py file whenever it starts up. You can use this file to set up your working environment or execute commonly used Python commands such as importing the maya.cmds module.

The userSetup.py script is executed during the initialization and setup phase of Maya; therefore, only commands which set up your working environment and have no dependencies on Maya functionality can be successfully run in this script.

NoteYou can use maya.utils.executeDeferred() to delay code execution until after the Maya scene is initialized. For more information, see maya.utils.
  1. Create a file named userSetup.py in the following folder:
    • Windows: :\Documents and Settings\\My Documents\maya\\scripts
    • Mac OS X: ~/Library/Preferences/Autodesk/maya//scripts
    • Linux: ~/maya//scripts
  2. In the userSetup.py file, type the commands you want Maya to run on start up; for example, import maya.cmds as mc.
    NoteMake sure you save the file with the right extension (.py).

Adding items to your Python path

To add items to your path in Python, do one of the following:

  1. Set PYTHONPATH in your Maya.env file, or in your environment before you run Maya
  2. Append to sys.path in your userSetup.py or other script once Maya is running.

Here is an example of appending sys.path

import sys sys.path.append( '/Users/jdoe/maya/Scripts' )

MEL and Python importing

If you have a MEL script in your path, you do not need to source it before accessing any single global procedure it contains with the same name. However, Python requires you to import a script explicitly before accessing any classes or functions it contains; for example:

# This will access the function "bar" in the file "foo.py"
import foo
foo.bar()

Using Python

Using Python

There are a number of differences in how Maya commands are invoked in Python relative to how they are used in MEL, given that the languages are so different.

Here are the basics to getting started with Python in Maya:

Entering Python commands in Maya

There are several ways of entering Python in Maya.

Script Editor

To facilitate having both MEL and Python scripting at the same time in Maya, the Script editor has been modified to have separate tabs for each language. Statements entered into the MEL tabbed window are sent to MEL to be processed; similarly, statements entered into the Python tabbed window are processed by Python.

Returned results from Python come prefixed with the Python comment character (#).

For more information, see Script editor.

Command line and Shelf

You can also enter short Python commands into the command-line. A toggle allows you to enter either MEL or Python commands.

You can -mouse drag Python scripts to the Shelf, just like MEL scripts. A dialog box appears asking whether your script is a Python or MEL script.

Maya Python module

The Python bindings for all of the native Maya commands are in the maya.cmds module. In order to access these commands, you must enter the following in the Python tab of the Script editor in each session:

import maya.cmds

This allows you to use Maya commands. For example:

maya.cmds.ls()
maya.cmds.sphere( radius=4 )

You can import Maya commands to a different and shorter namespace:

import maya.cmds as cmd
cmd.sphere()
TipYou can import maya.cmds automatically in the userSetup.py file. You can modify this to use your preferred prefix; for example:

import maya.cmds as mc mc.sphere()

For more information, see Initializing the Maya Environment in and for Python.

NoteAlternatively, you can import the Maya commands into the top-level namespace using:

from maya.cmds import *

after which you can use a briefer way to reference Maya commands:

ls() sphere( radius=4 )

WARNING: Importing to the top-level namespace overrides definitions from Python built-in and other modules.

For example, Python has its own help system and a call to the Python version of help produces output that is specific to Python. A call to maya.cmds.help provides help about Maya commands. Importing maya.cmds into the top-level namespace would result in not being able to access Python help.

Flags (named arguments)

Flags are handled differently in Python than they are in MEL. MEL was designed with a shell command style syntax.

For Maya commands in Python, the command argument syntax has been adapted in a way that is natural for Python. As a result, flags—both long and short forms—are passed to commands as named arguments. The name of the argument is the flag name and the flag’s arguments are passed to the named argument.

Single arguments

The MEL sphere command is:

sphere -radius 4;

In the Python version, the flag radius is referenced as a named argument and, since there is a single argument, the value is passed as follows:

maya.cmds.sphere( radius=4 )

Multiple arguments

If the flag has multiple arguments, then the arguments need to be packed into a list or a tuple. Here is an example of a command with a flag that has three arguments.

# With a tuple maya.cmds.ambientLight( rgb=( 0.2, 0.3, 0.4 ) )
# With a list maya.cmds.ambientLight( rgb=[ 0.2, 0.3, 0.4 ] )

Required arguments (True/False)

Named arguments must have a value associated with them. However, not all Maya flags require a value (for example, ls -sl). In order to maintain a consistent syntax, the Autodesk Maya Python implementation requires you to assign a boolean argument to those flags that do not normally take any arguments. If the boolean value is False, then the flag is ignored; if it is True, the flag is used. For example:

# Pass selection flag maya.cmds.ls( selection=True )
# Selection flag is ignored here maya.cmds.ls( selection=False )

Multiple named arguments

Some flags may be used multiple times in one command call. For example, in MEL:

ls -type nurbsSurface -type transform;

In Python, you would use the named argument type and pass the values in a list or a tuple.

maya.cmds.ls( type=['nurbsSurface','transform'] )

In the case where a flag is used multiple times and has multiple arguments, the value is a list of lists. Tuples may be used instead of lists, so you may use a tuple of lists, a list of tuples, or a tuple of tuples. For example, the curveOnSurface command in MEL:

curveOnSurface -d 3 -uv 0 0 -uv 0.3 0.5 -uv 0.5 0.6 -uv 0.9 1.0 surface1;

In Python:

maya.cmds.curveOnSurface( 'surface1', d=3, uv=[(0,0),(0.3,0.5),(0.5,0.6),(0.9,1.0)] )

If you use more than one argument flag, Python returns an error (‘Duplicate keyword argument’).

Ranges

There are three types of ranges in Maya commands: time, index, and float. All ranges must be specified using tuples in Python. Any tuple may have either one or two values. A tuple with one value is specified as a value in brackets with a single comma; multiple single-valued tuples are specified using set notation (see Multiple named arguments).

As well, time ranges support units. To specify units, you must use strings. You can mix units as each value is parsed separately.

These are valid time ranges:

(1,) (1,10) ('1sec','10sec') ('1min:2min')

The following table uses the cutKey command as an example of specifying time and index ranges.

MEL range Meaning Python range

-time 10pal

Cut the key at frame 10 (PAL format)

time=('10pal',)

-time 1.0sec -time 15ntsc -time 20

Cut the keys at time 1.0 second, frame 15 (in NTSC format), and time 20 (in the currently-defined global time unit).

time=[('1.0sec',), ('15ntsc',), (20,)]

-time "10:20"

Cut all keys in the range from 10 to 20, inclusive, in the current time unit.

time=(10,20)

-time "10:"

Cut all keys from time 10 (in the current time unit) onwards.

time=('10:',)

-time ":10"

Cut all keys up to (and including) time 10 (in the current time unit).

time=(':10',)

-time ":"

Cut all keys

time=(':',)

-index 0

Cut the first key of each animation curve.

(Indices are 0-based.)

index=(0,)

-index 2 -index 5 -index 7

Cut the 3rd, 6th, and 8th keys.

index=[(2,),(5,),(7,)]

-index "1:5"

Cut the 2nd, 3rd, 4th, 5th, and 6th keys of each animation curve.

index=[("1:5",)]

Changes to certain command flags

Certain flag changes to Maya commands are necessary because the arguments for multi-use flags in Python must be passed as a list to the flag. This causes a problem for commands in which different multi-use flags must be mixed-and-matched. Since each multi-use flag’s arguments are provided in a separate list in Python, there is no way to intermix them. The few commands which relied on this have been extended so that a single multi-use flag handles the job of the individual multi-use flags.

These commands include:

  • polyAppendVertex: new append flag which can be used in place of the point, vertex, and hole flags.
  • polyAppend: new append flag which can be used in place of the point, edge, and hole flags.
  • polySplit: new insertpoint flag which can be used in place of the facepoint and edgepoint flags.
  • polyCreateFacet: the existing point flag as been modified so that it may be also used to specify holes.
  • roundConstantRadius: a new side flag replaces the use of sidea and sideb that are supposed to be intermixed.

The use of all of these flags is documented in the CommandsPython reference documentation.

In all cases, the flags are backwards compatible. All old flags have been left in place.

Arguments and objects

The curveOnSurface example above also illustrates another Python syntax requirement. Besides flags, Maya commands may also take arguments and objects. Arguments are values of a fixed type that are required by a command. For example, the move command takes three arguments representing the x, y, and z values for the move. Objects are the entities upon which a command operates (for example, an object in a scene or a UI element). There can be a variable number of objects for a command and sometimes they are implicit, based on the current selection list.

Objects and arguments are passed to commands as they would be in MEL, but they must be passed in the following order:

command arguments object flags/named arguments

This is different from MEL where the ordering requires that objects appear at the end of the argument list. However, Python requires that named arguments come after all other arguments.

Summary of argument types

The following table shows a summary of the flag (named argument) types you can use in the Maya Python module.

Flag type Example Comment

plain flag

MEL: ls -selection

Python: maya.cmds.ls( selection=True )

Flags with no arguments get a boolean True/False switch

flag with single argument

MEL: sphere -radius 10

Python: maya.cmds.sphere( radius=10 )

flag with multiple arguments

MEL: ambientLight -rgb 0.2 0.3 0.4

Python: maya.cmds.ambientLight( rgb=( 0.2, 0.3, 0.4 ) )

use a tuple to specify multiple arguments

multi-use flags

MEL: ls -type nurbsSurface -type transform

Python: maya.cmds.ls( type=['nurbsSphere','transform'] )

Use a list to hold the multiple flag values

multi-use flags with multiple arguments

MEL: curveOnSurface -d 3 -uv 0 0 -uv 0.3 0.5 -uv 0.5 0.6 surface1

Python: maya.cmds.curveOnSurface( 'surface1', degree=3, uv=[(0,0),(0.3,0.5),(0.5,0.6)] )

Use list of tuples.

(You can also use a tuple or tuples, a list of lists, or a tuple of lists.)

command arguments

MEL: move 2.0 1.0 1.0

Python: maya.cmds.move( 2.0, 1.0, 1.0 )

The same as MEL except arguments must come first

command arguments with flags

MEL: move -objectSpace 2.0 1.0 1.0

Python: maya.cmds.move( 2.0, 1.0, 1.0, objectSpace=True )

command objects

MEL: select nurbsSphere1

Python: maya.cmds.select( 'nurbsSphere1' )

Same as MEL

command objects with arguments and flags

MEL: move -objectSpace 2.0 1.0 1.0 nurbsSphere1

Python: maya.cmds.move( 2.0, 1.0, 1.0, 'nurbsSphere1', objectSpace=True )

Objects must come before flags

query where a flag/argument takes a value

MEL: skinCluster -q -inf;

Python maya.cmds.skinCluster (q=True, inf=True)

Query flag requires a boolean True.

query where a flag/argument does not take a value

MEL: skinCluster -inf joint1 -q -dr;

Python: skinCluster (q=True, inf='joint1', dr=True)

Standard input (stdin) implementation

Python supports reading from STDIN (standard input). In a Python script, this is accomplished by reading from sys.stdin or calling raw_input. When Maya is running in GUI mode (as opposed to batch mode), Maya intercepts these calls from Python and prompts you with a dialog box where you can type your input.

Maya overrides sys.stdin with its own implementation. If you want to use Python’s native stdin object, you can do so by referencing sys.__stdin__.

MEL/Python communication

A new MEL command—python—takes a string and passes it to be executed in Python. The python command attempts to convert the result into a MEL type.

python( "import maya.cmds" )
python( "maya.cmds.ls" )
NoteOnly strings with a single Python statement return a result. This is a limitation currently imposed by Python.

Python has a more sophisticated type system than MEL, so it is not possible to convert all Python data types into native MEL types. The python command converts those that it knows how to handle. For the rest, it requests a string representation of the object and returns that.

The following table shows the currently supported mappings:

Python Return Value MEL Conversion

string

string

unicode

string

int

int

float

float

list containing numbers, including at least one float

float[]

list containing only integers or longs

int[]

list containing a non-number

string[]

anything else

string

empty Python list

empty string array (string $array[])

Calling MEL from Python

To call MEL from Python, use the maya.mel.eval() function. It can do a better job of conversion than the MEL python command since Python has more flexible type support.

You must import the maya.mel module to use this command; that is:

import maya.mel as mm mm.eval("polySphere;")

Here is a table of the supported conversions:

MEL Return Value Python Conversion

string

string

int

int

float

float

vector

3-tuple of values

matrix

list of lists where each sub-list in the list contains one row of the matrix

string[]

list of strings

int[]

list of ints

float[]

list of floats

vector[]

list of 3-tuples

Positional arguments

Positional arguments refer to the arguments that UI elements pass to their callback scripts. For example, the callback MEL script for a float slider control could contain #1. The value of the float slider is substituted for this positional argument when the callback is run.

For Python, two different ways of substituting values from controls in callbacks are supported. If the callback is a string which is to be evaluated, then Maya does string substitution as in MEL. However, Python’s format operator is used to do the substitutions. The format operation is passed a dictionary of items for the substitution where the names of the values are 1, 2, and so on. For example:

maya.cmds.floatSlider( cc="print '%(1)s'" )

(The dictionary is applied to the string later, before it is executed. The floatSlider command formats the string with the current slider value before executing the script. You provide the format string and the UI element provides the dictionary for the format operation.)

The second style of Python callback uses a compiled function, where Maya passes the values as arguments to the function:

def doPrint( arg ):
 print arg
cmds.floatSlider( cc=doPrint )

With callback functions, you get an error message if your callback does not take the correct number of arguments.

def badStuff():
 print "bad"
cmds.floatSlider( cc=badStuff )

When you move the slider, you see this error:

# TypeError: badStuff() takes no arguments (1 given)

If you want to create a callback that works with any number of arguments, use a variable argument list:

def genericCallback( *args ):
 print( "args: " + str ( args ) )
cmds.button( command=genericCallback )

Errors and Warnings in Python

In order for the status line in Maya to appear in red or purple when an error or warning is encountered, add this section of code to your script and use these functions:

def pyError( errorString ):
   """ print an error message """
   import maya.mel as mel
   try: 
      mel.eval(_NOL10N('error "%s"') % errorString)
   except: 
      pass
def pyWarning( warningString ):
   """ print a warning message """
   import maya.mel as mel
   try: 
      mel.eval(_NOL10N('warning "%s"') % warningString)
   except: 
      pass

Python API in Maya 2008

Python API in Maya 2008

This evening I thought I'd give the Maya 2008 Python API code a try, and it was pretty cool. In the past in the Maya API you always have to add code to your plugin, re-compile, perhaps even close Maya and re-start it to get the updated plugin to run... or at least you have to unload it and then reload it. So tonight I thought I'd give the new Maya Python API code a shot and it is soooooooooooooo cool. It took a bit to get the syntax right, since obviously static member functions don't exist in Python with the same Syntax as C++.

I.e. if you want to print something to the script output you can rock the 'ol school MGlobal style...

In C++ it's:
MString information("This is my display string");
MGlobal::displayInfo(information)

In Python it's:
import maya.OpenMaya as OpenMaya
information = "This is my display string"
OpenMaya.MGlobal.displayInfo(information)

So the usual new weirdness to get used to. I guess one obvious and awesome change is that there is no MString anymore. This is a good idea of course since Python's string stuff is just so awesome and it was a good choice to stick to that. The lack of types in Python is kinda nuts when you are dealing with random MFn's in Maya API and all that craziness, but I guess if you keep good coding style then it's probably not too insane.

As I was coding I realized that I had completely forgotten how to do a for loop in Python. I was trying some ugly syntax to try to iterate over an MItSelectionList iterator... and it totally didn't work. I ended up doing a

while not iter.isDone():
....do stuff
....iter.next()

And that did the trick. Totally weird when you are so used to one language and another one is as different as this. I don't really think for loops are a good idea for iterators in the Python API, but I guess maybe there is a nicer way to do it. I suppose in the classic Maya C++ API examples of using a for loop for an iterator, you don't even use the initialization condition so I guess a while loop really does the job anyway.

Pretty awesome stuff.

Another thing I found weird (for some reason, although on second glance it seems quite like the expected syntax) is that you need to kindof do this weird method call to get an MObject or MSelectionList or whatever you might want, and you set it to the standard dynamically-specified Python type.

I.e. if you want to get an the current active selection list, you do this...

import maya.OpenMaya as OpenMaya
selList = OpenMaya.MSelectionList()
OpenMaya.MGlobal.getActiveSelectionList(selList)

So this seems kindof verbose, but the Maya API is generally kindof verbose (at least if you're comparing it to just doing the same thing in MEL), and so I guess it's as expected. But there is some weirdness like the lack of :: namespaces, and the fact that MSelectionList selList(); is now selList = OpenMaya.MSelectionList()?!??!! Haha so weird. But it makes sense. Just something new to get used to.

Anyway it's a reaaaaaaaaaaaaaaaaaally awesome thing that this is available now, and actually I've always really liked MEL because it's really easy to prototype something or just code something super fast and see if it works before you spend ages on it. So this gives you that speed and interpreted language benefit, but with the very simple ability to copy and paste (pretty much) your code from the Python script window into your C++ file after you get it working on smaller examples inside of Maya. Then you can compile it and try again on larger examples with your plugin. Sweet. This is going to be pretty fantastic, and I am actually quite impressed and excited at the possibility of using the Python API hand-in-hand with the C++ API for quicker development.

Every time I look at the Python changes in Maya 8.5 onwards I am pretty much blown away by how big of a change this is, and what it means for production software development in general. Very, very nice. And I am so psyched that it's really easy to move your knowledge from one to the other. See my thoughts on Python in Maya from a couple of weeks ago. It's nice to now have given myself an introduction to the Python API in Maya and to get an idea of where I can benefit from it. Good stuff.

Creating A Stormy Ocean In Maya

Creating A Stormy Ocean In Maya

By Aziz | Editing by Dr Diablo | Maya 8.5 | Beginner

This tutorial is going to show you how to create a realistic animation of a stormy ocean wave using fluid effects. Our final output will be a video shot through a cylinder stand camera placed right on top of the ocean waves to add more thrill to the scene. Here is a sample video of our effect:

Our tutorial will be divided into the following sections:

  1. Creating the ocean surface.
  2. Setting the stormy ocean characteristics.
  3. Adding the camera to the scene.
  4. Adding fog to the scene.
  5. Rendering the scene.

Starting Off And Creating The Ocean Surface

To start off, fire up Maya. If you are not in the Dynamics module interface, hold down the H key on your keyboard, and then left click anywhere on the scene and drag the mouse onto Dynamics. This will change the menu buttons on the top panel of Maya.



From the top panel, go to Fluid Effects>Ocean>Create Ocean and click on the Option Box as shown in the screenshot below.

An attributes window will open, check the Attach to Camera and Create Preview Plane boxes. Preview Plane Size is the preview plane that shows the effect of ocean on the scene when playing with attributes, you can give it any value you like. In this case I gave it a value of 15 which is pretty reasonable while playback, you can forward play the animation if you would like to check the ocean's movement flow.

The bigger preview plane size the slower in playback, do not increase the size beyond your computer's specs. The preview plane is not render-able it is just for illustration and visual clue while checking attributes.

Your ocean should look something like this now in perspective view.

While the preview plane is still selected, hit Ctrl+A to open up the Attributes Editor. Once the Attributes Editor appears click on the Ocean Preview Plane1tab, you will come across few options over here like Resolution, Color, Displacement, etc. Resolution increases the segments of the preview plane and that will lead to a smoother result on the scene. However, the increase in Resolution could lead to lower playback speed and system performance, in other words, rendering will take much more memory out of your system and preview playback will be slower than usual. Color and Displacement are locked, you don't need to play with those so just leave them at their default values. Height Scale increases the height displacement of the preview plane. Make sure you also keep it at it's default value.

Once you are done with Preview Plane 1 click on the Ocean Shader tab. We are going to spend most of our time here to modify and achieve the desired shape of our ocean.

Creating The Stormy Ocean

Creating a specific ocean effect simply requires using specific configuration in the Ocean Attributes rollout. To start off, simply expand the Ocean Attributes rollout to reveal its parameters. Assign the values stated below:

Scale, 1.000
Wind UV, -0.700 | -0.700
Wave Speed, 2.000
Observer Speed, 0.200
Num Frequencies, 20.000
Wave Dir Spread, 0.200
Wave Length Min, 0.200
Wave Length Max, 100.000

Go down to find the Wave Height rollout beside the color coded window. Set the Interpolation option to Smooth and add some points in accordance to your desired shape.

Scroll down to the Wave Turbulence rollout, set Interpolation to Smooth and play around with the Wave Height the same way we did before.

Scroll down to Wave Peaking, set Interpolation to Smooth, play around with the the settings to get your random ocean effect by adding some points along the graph to get peaking ocean waves.

Wave Peaking basically works well together with Wave Height. Again, change the Interpolation to Linear, play around with the settings and add some points along the graph to get peaking ocean waves.

The final step here is again adding Foam. Find the Foam options under the Wave Peaking rollout, set the parameters as specific below:
Foam Emission, 0.140
Foam Threshold, 0.675

That's it, you can create a test render to get an image similar to this:

Attaching A Camera To Capture The Surface Of The Water

We will now continue this tutorial with a stormy ocean. First off, create a cylinder or any geometry you like to use and make sure you fairly increase its height.

Create a Camera from Create>Cameras>Camera, and place it on top of your object. You can move the camera around using the Move Tool from the panel on the left.

While the Camera is still selected, hold Shift and left click on the Cylinder to select them both. Go to Edit>Parent, this will have the Cylinder move along wherever you move the Camera.

Its time to attach camera to the surface of ocean. With the parent object still selected go to Fluid Effect>Ocean>Make Motor Boats, this will attach the parent object to the surface of ocean and makes it move as the ocean moves.

If you play your animation you will see the parent object moves along as the ocean does. To render your scene from the camera's angle, go toWindow>Rendering Editors>Render View. Render View window will pop-up, go to Render>Render>camera1 as shown in the screenshot below.

This is my scene rendered from the camera1's angle.

Adding Fog

If we apply a fog the same way we did to the calm ocean, the whole scene will be full of physical smoke, we only need a small portion of fog for the stormy ocean. Start off by going to Window>Rendering Editors>Render Settings.

From the Render Settings Window, choose Maya Software as the renderer to be used and click on Maya Software tab. Scroll down to bottom and click onRender Options to expend it. Click on the box which is right next to the blank text field. It automatically adds environment fog and opens up an attributes editor to adjust the fog's parameters.

This should do it for the fog, here is how my rendered scene looked like

At this point your ocean is completely ready for either a single frame rendering job or an animation as we have connected the camera to the ocean's motion and it will move accordingly to its waves, to export your animation go to Window>Rendering Editors>Render Settings.

The Render Settings menu will popup. Change the File name prefix to the name of your animation. Change the Image format to .AVI. Change the Start frame and the End frame according to how long your animation is going to be. And finally, choose which camera you want to source render from theRenderable Camera drop down menu.

Don't forget to change the compression of the movie file you are creating according to a type of file that you can play, e.g. DivX.

Change your module interface to Rendering by holding down H anywhere on your scene, left click and drag the mouse onto Rendering. This will change the menu buttons on the top panel of Maya. Go to Render>Batch Render and wait for your movie to be completely rendered frame by frame, this process is going to take time.

Here are my final results.

This concludes our tutorial, I hope that you've learnt something new from it, feel free to post in the Oman3D Forum for any comments or questions or to get instant feedback.

- End of Tutorial.