Thursday, 3 February 2022

Sequence 2 Video

This handy little script will take any image sequence, exr, png, jpg etc, and combine it into a h264 mp4 video. 

There is a bat file in the repo below that needs to be added to a menu in windows. Open an explorer window and type "shell:sendto" in the address bar. Place the seq2Vid_CG.bat file in here and edit it so that it points to the locaiton of the downloaded Seq2Vid_v03.py

Once this has been done and FFMPEG has been installed (in C:/Dev/FFMPEG/bin....) you can now RMB on any image from a sequence and click "Send to" and then Seq2Vid_v03.py. The script will then run in a command line and create a video preview, which will be in the correct locaiton based off our previosuly created folder structure (having used the FolderGeneratoin_v001.py script)


Wednesday, 26 January 2022

Max File Automation

As part of my plan to overhaul the pipeline at work I've created a few scripts to manage file creation and saving. The idea is to standardize file naming, render outputs and render passes with the plan to automate later stages of the pipeline such as auto creating previews and nuke projects.

-------------------------------------------------------------------------------------
As these scripts are getting larger and larger I've decided to share my public Git repo rather than pasting the entire code block here.
https://github.com/eoin-personal/Public-Repo
-------------------------------------------------------------------------------------


What this main script will do: 

  • Search the target drive for available project folders
  • Create max file in the correct location based of the project selected in the UI.
  • Set render outputs to the correct location with the correct naming convention.
  • Set all render passes to the studio standard.
  • Set 3D Studio Max settings (fps, render size) based of selection of a 16:9 or 360 project.
  • Allow for scene or asset generation with some different settings based on this choice.
  • Allow for the Version and Take up tools to work, maintaining the file naming convention and updating the render outputs when necessary.

The UI in action:


There are 3 additional scripts that I've created for the pipeline overhaul.

The first is a folder generation script. This contains 2 parts, a bat file and a python file. The bat file can be placed in any location on any drive and once the path inside points to the python file it will create a folder structure in the root of the drive the bat file is currently stored on. The name of this project will fit our current format  <Date>_<JobCode>_<JobName> with the user providing the job code and name and the script auto formatting the current date into a usable format.

The second and third files are for versioning up the max files created using the Max Project Generator script. These will maintain the correct naming conventions and update with new render paths if the prompt is answered with yes.

VersionUp_v001.ms

TakeUp_v001.ms

Wednesday, 27 October 2021

I fixed it.......for now

After putting the original script through the production pipeline I noticed a few errors. These had been fine when working off one max file, but once I used the loop to go through multiple max files the issues started to creep in. 
3DS Max stores variables once they are assigned and this is something I need to get used to when debugging. If I ran the script once and stepped through to solve an issue, any variables I had manually set during this would be locked in place till overwritten or Max was closed. This led to a variable not being set correctly in the loops and this only became apparent once I got the final results back, the files had rendered out correctly but not in the right folders. My first clue was that each image sequence was begin stored in the previous folder according o the order of the main loop.

The issue was with the render output filename and path, with the variable "verShotFolder" This variable was being set inside of an 'if' loop and not being stored outside of it afterwards. 
The solution was to create this variable at the beginning of the whole script as verShotFolder = ""

I also split some of that loop up as the...
if (doesfileexist verShotFolder) != true do
(makeDir verShotFolder)
...was being called the same no matter the result of the first loop.

----------------------------------------------------------------------------------------------------------------------

Debugging this code was a bit of a mission, but I feel I've learned a significant flag to watch out for in future coding exercises. If a variable from inside a loop is being called outside of it, that variable must be declared first, outside of the loop, so that the loop can fill it in, otherwise the variable from the loop will only hold the value assigned to it for the duration of the loop.

----------------------------------------------------------------------------------------------------------------------

maxFiles = getfiles @"O:\VirtualTour_VR\3D\Projects\Scenes\ScriptBackup\*.max"
::filein @"O:VirtualTour_VR\Scripts\DeadlineSubmitter_v01.ms"
mergeFileName = @"O:\VirtualTour_VR\3D\Projects\Scenes\ScriptTest\NovartisUpdatedHead01.max"
verShotFolder = ""
for i = 1 to maxFiles.count do
(
loadMaxFile (maxfiles[i])
verShotFolder = ""
---------------------------------------------------------------------------
----------- Update geo and texture

oldHeadGeo = $Char_Head
headParent = $Char_CTRL_Main
bandRemove = $Char_HeadStrip
innerHead = $Char_InnerHead

mergeMAXFile mergeFileName  #useMergedMtlDups
newHeadGeo = $NovartisUpdatedHead01
newHeadGeo.transform = oldHeadGeo.transform
newHeadGeo.parent = headParent
innerHead.parent = headParent
delete oldHeadGeo
delete bandRemove
viewport.setCamera $PhysCamera001
meditMaterials[1] = sceneMaterials["Head_Body"]
$Char_Body.material = meditMaterials[1]

---------------------------------------------------------------------------
----------- Make new folder for v2.2

renderSceneDialog.close()
rc=renderers.current
rc.output_saveRawFile=true
rendTimeType = 2
ogOutput = rc.output_rawFileName
verFolder = pathConfig.removePathLeaf ogOutput
verFolderTest = (filterstring (verFolder) "\\")[(filterstring (verFolder) "\\").count]

rendFileOuputSplit = (filterstring (ogOutput) "\\")[(filterstring (ogOutput) "\\").count]
versionUp =  (filterstring (rendFileOuputSplit) ".")
versionPt2 = versionUp[2]
versionPt2Solo = versionPt2[1] as integer
versionUpSolo = (versionPt2Solo + 1) as string
UppedVerFilename = versionUp[1] + "." + versionUpSolo + "_" + "." + versionUp[3]
--outputPath = verShotFolder + "\\" + UppedVerFilename

ogFileName = (filterstring (ogOutput) "\\")[(filterstring (ogOutput) "\\").count]
ogFileVerMain =  (filterstring (ogFileName) ".")[1]
mainVer = ogFileVerMain[ogFileVerMain.count]
targetVersion =  "v" + mainVer + "." + versionUpSolo
shotFolder = pathConfig.removePathLeaf verFolder
if (verFolderTest == "Intro") then
(
verShotFolder = (verFolder + "\\" + targetVersion)
)
else if (verFolderTest == "Outro") then
(
verShotFolder = (verFolder + "\\" + targetVersion)
)
else
(
verShotFolder = (shotFolder + "\\" + targetVersion)
)
if doesfileexist(verShotFolder) != true do
(
makeDir verShotFolder
)

---------- Set Vray render output to new version

outputPath = verShotFolder + "\\" + UppedVerFilename
rc.output_rawFileName = outputPath

---------- Save new max file version
maxFilePathSplit = (filterstring (maxfilepath) "\\")
parentMaxFolder = pathConfig.removePathLeaf maxfilepath
newMaxFileSave = parentMaxFolder
maxFileNameSplit =  (filterstring (maxfilename) ".")
maxFileVersion = maxFileNameSplit[2] as integer
maxFileVersioningUp = (maxFileVersion + 1) as string
newMaxFileName = maxFileNameSplit[1] + "." + maxFileVersioningUp + "." + maxFileNameSplit[3]
newMaxFileNameFullPath = maxfilepath + newMaxFileName
if (doesfileexist newMaxFileNameFullPath) != true then
(
saveMaxFile newMaxFileNameFullPath
)
else
(
messagebox "!!!Warning!!!\nA more recent max file already exists\nJob has been submitted anyway"
)

----------Send to deadline

_DlJobName = maxfilename
_Priority = 30
_Comment = "-- Submitted Via DLSubmitJob"
_UserName = "Eoin"
_Group = "singles"
DLRenSubmit _DlJobName _Priority _Comment _UserName _Group 
)



Wednesday, 13 October 2021

Pipeline Beginnings

 I've been learning to code over the past few years but have recently started a course "TD Certification" by Allan Mckay. I've decided to track my progress here so will be posting up any scripts I work on for work and anything else I can think to script.

----------------------------------------------------------------------------------------------------------------------

I've found in the past that I have struggled to find applications for the coding I was learning, but as a result of this course I feel I now have enough knowledge, and the ability to plan out a script. I had always found blank page syndrome difficult to deal with in relation to coding, never really knowing what could be done and how to go about it. Through the course I have found out that the easiest way is to break any job up into single steps and then work on each one of those one by one, combining them where needed. The course began focusing on Maxscript but towards the end we have moved on to Python, where I would have a small amount of experience which I am now finding I have a greater understanding than i thought I did beforehand.

----------------------------------------------------------------------------------------------------------------------

At the bottom of this post is the code for the first situation I have found where I can apply what I have learned to a task at work - I needed to replace geometry and update a texture for 15 files and then submit each one to Deadline with a versioned up folder and file name. Below is the plan I came up with to get myself started.

1.Import new head
2.Extract new texture
3.Apply new texture to body
4.Align new head to old one
5.Attach head to 'Char_CTRL_Main'
6.Remove old head and band
7.Version up render output
8.Turn render on
9.Make sure correct viewport is rendering
10.Save new max file
        11.Send to farm

While going through these steps I realised I could skip step 2 by bringing the new texture and setting a flag <#useMergedMtlDups> on the import function to specify to use the updated merged material instead of the scene one. EDIT: this unfortunately did not work as planned at which point I figured out how to transfer a texture from the imported geo to the rest of the geo in the scene that needed it to be applied on.

At the beginning of this exercise I had to pipe certain text items directly in, mainly around the version number for the max files and render outputs, but as I progressed I figured out some ways to extract these with code, thus allowing for the script to be used beyond 'v2.1'.
At present the only things that need to be entered manually are the location of the max files folder, and the assets that need to be replaced and/or deleted.

I really enjoyed this exercise, it was a great excuse to test out what I've learned over the last 2 months, both in terms of knowledge and how to go about building a script. Plenty of Google searching and testing single lines of code, but the satisfaction of getting something like this to work is hard to put to words.

----------------------------------------------------------------------------------------------------------------------

I am hoping I will get some more jobs that will allow me to push myself further, and I have some plans for a studio pipeline overhaul, to change the folder and file naming structure to allow for much greater automation of simple tasks.

----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

maxFiles = getfiles @"O:\VirtualTour_VR\3D\Projects\Scenes\*.max"
for i = 1 to maxFiles.count do
(
loadMaxFile (maxfiles[i])

::filein @"O:\VirtualTour_VR\Scripts\DeadlineSubmitter_v01.ms"
mergeFileName =  
        @"O:\VirtualTour_VR\3D\Projects\Scenes\ScriptTest\CharUpdatedHead01.max"

---------------------------------------------------------------------------
----------- Update geo and texture

oldHeadGeo = $Char_Head
headParent = $Char_CTRL_Main
bandRemove = $Char_HeadStrip
innerHead = $Char_InnerHead


mergeMAXFile mergeFileName  #useMergedMtlDups
newHeadGeo = $UpdatedHead01
newHeadGeo.transform = oldHeadGeo.transform
newHeadGeo.parent = headParent
innerHead.parent = headParent

delete oldHeadGeo
delete bandRemove

        meditMaterials[1] = sceneMaterials["Head_Body"]
        $Char_Body.material = meditMaterials[1]

viewport.setCamera $PhysCamera001

---------------------------------------------------------------------------
----------- Make new folder and rename output path

        renderSceneDialog.close() rc=renderers.current rc.output_saveRawFile=true rendTimeType = 2 ogOutput = rc.output_rawFileName verFolder = pathConfig.removePathLeaf ogOutput verFolderTest = (filterstring (verFolder) "\\")[(filterstring (verFolder) "\\").count] rendFileOuputSplit = (filterstring (ogOutput) "\\")[(filterstring (ogOutput) "\\").count] versionUp = (filterstring (rendFileOuputSplit) ".") versionPt2 = versionUp[2] versionPt2Solo = versionPt2[1] as integer versionUpSolo = (versionPt2Solo + 1) as string UppedVerFilename = versionUp[1] + "." + versionUpSolo + "_" + "." + versionUp[3] outputPath = verShotFolder + "\\" + UppedVerFilename ogFileName = (filterstring (ogOutput) "\\")[(filterstring (ogOutput) "\\").count] ogFileVerMain = (filterstring (ogFileName) ".")[1] mainVer = ogFileVerMain[ogFileVerMain.count] targetVersion = "v" + mainVer + "." + versionUpSolo if (verFolderTest == "Intro") or (verFolderTest == "Outro") then ( verShotFolder = (verFolder + "\\" + targetVersion) if doesfileexist(verShotFolder) != true do ( makeDir verShotFolder ) ) else ( shotFolder = pathConfig.removePathLeaf verFolder verShotFolder = (shotFolder + "\\" + targetVersion) if doesfileexist(verShotFolder) != true do ( makeDir verShotFolder ) ) 
rc.output_rawFileName = outputPath


---------- Save new max file version

maxFilePathSplit = (filterstring (maxfilepath) "\\")
parentMaxFolder = pathConfig.removePathLeaf maxfilepath
newMaxFileSave = parentMaxFolder

maxFileNameSplit =  (filterstring (maxfilename) ".")
maxFileVersion = maxFileNameSplit[2] as integer
maxFileVersioningUp = (maxFileVersion + 1) as string
newMaxFileName = maxFileNameSplit[1] + "." + maxFileVersioningUp + "." +                                    maxFileNameSplit[3]
newMaxFileNameFullPath = maxfilepath + newMaxFileName
if (doesfileexist newMaxFileNameFullPath) != true then
(
saveMaxFile newMaxFileNameFullPath
)
else
(
messagebox "!!!Warning!!!\nA more recent max file already exists\nJob has been submitted            anyway"
)
----------Send to deadline

DLRenSubmit _JobName _Priority _Comment _UserName _Group 

)


Friday, 5 June 2015

Unity

So I've started looking into some games studios recently and I decided it would be a good idea to try and get to grips with Unity, the software that most of them use.

I had no experience with game engines so it took a lot of tinkering and problem solving but I managed to string together a simple idle, walk and run cycle.

I started out creating a basic idle cycle with a character from my time on iAnimate. While I was happy with the cycle, whenever I tried to import it into Unity the mesh broke, with the head detatching from the body, and none of my animations were transferred across.


I tried several solutions to get the character into Unity but I reached the conclusion that the characters I had were not built to go into it. I searched online and through all my rigs to see if one would be suitable to transfer across while also allowing me to animate with it in Maya but could not find any. So I took the Max rig, removed the mesh from the rig and re-rigged it myself using abAutoRig, found at http://www.supercrumbly.com/3d.php?sid=173#.VXGcm89VhBc


With this rig I was able to animate all my cycles and import them into Unity. On each cycle I had to bake the animation into the bones and then export the bones and mesh as an FBX.
I imported the base rig, mesh and bones, into unity and then imported my 3 cycles. Using the animate tab I created transitions between the idle and walk and the walk and run cycles.


I found this exercise really interesting and rewarding. I always enjoy trying out a new piece of software and I found most of the issues I encountered helped me out with figuring out how unity works at a basic level, at least as far as creating animations that will work inside of it.

Tuesday, 27 January 2015

Parkour 2.0

My Final project as part of the Ianimate course. The brief was to have a character run from one location to another and to incorporate some acting and camera movement and cuts. I feel a lot of what I have learned over the previous two shots came through in this one and I tried to push the 2D aspect of the finished piece instead of focusing on the 3D world space of the scene so much.



And that's it for Ianimate for now, I got a huge amount from the course, learning a proper workflow which was something I had struggled with before, really pushing my poses and getting them locked down before moving on to breakdowns and knowing at what point I'm ready to start polishing to avoid confusion at a later stage. I may return to complete another semester at some stage but for now I'm gonna take what I've learned and apply it to the work I'm currently involved with.

Monday, 17 November 2014

iAnimate Work - Push

Second project in the iAnimate class. The brief was to do a push/pull/lift so I eventually settled on animating a mime artist. I figured it would help me push the pantomime acting as mimes must be very expressive.


Monday, 3 November 2014

iAnimate Work - Sneak

This was the first project I did as part of iAnimate workshop 3, "andvanced body mechanics and pantomime acting".
Our task was to animate a walk or sneak, and seen as I'd animated 2 sneaks already, I decided to try and get it as polished as I could, while I had the help and tuition of Michael Kiely.



Thursday, 28 August 2014

Rigging On The Fly

I got this character from Basim Ahmed who's working in Piranha bar at the moment, he had rigged it himself but I wanted to try my hand at creating an animator friendly rig with controls I thought would be helpful as an animator. The workflow I used with the biped was useful here to a point though I had to edit it quite a bit due to the different anatomy.

the wings where the biggest challenge in this rig, I wanted to have as much control as i cud over them, with some set driven keys to allow for easy posing and curving of the basic shape, while not cluttering it up with too many controls or a complex bone system that would make skinning extra difficult, I learned this part the hard way after a bit of time spent trying to fix what could not be fixed. I also wanted to have a control that made the wings and wing covers fold in so that you don't have to pose them in every time you want them closed.

All of this involved a lot of parenting, grouping and figuring out what combination of parenting, constraining and use of the connection editor as well as the node editor. I also employed some of the dorrito effect I had learned from the previous rig to get the controllers on the lower parts of the wing to move with the deformations. I found this part highly enjoyable, trying to figure out the best, or sometimes only, way that something will work with all the incoming and outgoing connections


Below is a quick test animation I did with the rig.


Tuesday, 19 August 2014

Fully Rigged

I pushed on from my rigged head to rig a full biped character using the skills and techniques I learned on the last piece and adding in a lot more. The character I rigged is XSI man exported from Softimage and brought into Maya

The extra bits I learned and implemented in the rig:

  • How to rig a biped character, including setting up the hierarchy and constraints for the controls and what bones to place where.
  • How to set up the reverse foot lock so that he can roll on the ball/toes/heel.
  • Creating a setup where the animator can switch between FK and IK allowing for greater control of the arms. Three sets of arm bones were created, one for FK, one for IK and one which blends between these two to hold the geometry.
  • Adding a twist system for the wrists and legs to avoid mesh pinching when the wrist/ankle are rotated.
  • Using extra bones in the knees and elbows to maintain volume when the arms and legs are bent. These extra bones find the average angle of the bones on either side of it to orient themselves in the correct direction.
  • Using clusters to control deformations on the face.
  • Facial controllers that will follow the deformations caused by the jaw while still allowing control over the shape of the mouth AKA the "dorrito effect".
  • A constraint system led by custom attributes on the controllers for knee/elbow/eye controllers to follow parts of the rig or be free in world space.

Thursday, 31 July 2014

Let the rigs begin

My first attempt at rigging a human head.

It involved using bones and some controls for eyebrows and jaw. and creating blend shapes to achieve a few emotions. The model I rigged is "Samuel" by Leah Apanowicz, found on Creative Crash at http://www.creativecrash.com/3d-model/samuel-free-3d-model

What I've learned:
Lots about skinning and weights due to the huge poly count on the model.
How to build a basic facial rig and model the blend shapes using the sculpt tools to enhance it.
How to link blend shapes to a GUI for ease of access.
How to link blend shapes to the jaw controller to create accurate skin stretching.

Next step is to find a lower res model and try again, this time rigging the entire body and a full range of emotions along with all the controllers I can think of.


Monday, 7 July 2014

Modo Ninja

We've been trying out some new software packages in work. I was asked to test out the animation abilities in Modo. Some great features in it, really nice coming from a classical animation background, the spacing chart allows you create key poses, in-betweens and breakdowns with ease before you have to look at the timing, similar to animating in stepped but a lot more intuitive.  The onion skinning, and motion path and arc tracking are great for sorting out your trajectories. Part of the aim of this task was to see how fast I could animate a basic scene in Modo so I limited the amount of time I had to complete it, took me roughly 8 hours, and I had spent a couple of hours getting used to the basics of Modo before i jumped into it.


If the video isn't playing properly try opening it in youtube, or a different browser if you have it

Monday, 16 June 2014

Parkour

Decided to build on the wall climbing exercise I did last year, using a proper character rig, Malcolm, and creating a longer sequence with some extra moves. Collected reference from different parkour videos online and used these to build a course for Malcolm to take. I tried to really push the speed of the movement to get an extra bit of cartooning into it. Once i had the scene planned out it took roughly 2 weeks of animating

Parkour from Eoin Coakley on Vimeo.

Thursday, 29 May 2014

Decks Setup

I made my mixer to go with my set of decks and created a night-club-esque lighting setup. So so many layers of texture on the mixer with all the labels. Looking forward to getting back to some animating now, as I revisit my free running exercise from a few months back


Wednesday, 7 May 2014

Decks

Some more practicing with modelling and lighting here. This one took a bit more time than any of the individual pieces in the previous post, getting the lighting, texturing and reflections to match my reference photos was quite tricky.

Tuesday, 29 April 2014

Modelling

I've been practising some modelling and texturing in Softimage for the past few weeks. Started off with a model plane/spaceship hybrid, following a tutorial and then modifying it to add some extra detail and the textures.


I wanted to create a work area for the model, basing it off the desk in my room. I added in some other models, such as the toy robot, the lamp and the paint materials and then experimented with the light coming in through the gaps in the blinds.



To push this model further I decided to model my own bedroom, with the desk as above. I made some small modifications, such as changing the look of the box where the TV sits, to add some extra colour to the room.


I modelled up a pair of hands, rigged them using GEAR and then animated them clapping.







Monday, 7 April 2014

Favourite Adequachulance

I was given the task of doing a lipsync from the 11second club archives, I ended up doing 2 of them over the course of 6 to 8 weeks. Started off juggling between the 2 of them, but eventually decided I was better off focusing on one at a time, and getting it as finished as I could before moving on to the next one. Really tried to push the posing on these 2, and both required a complete restart after a couple of weeks on each. Well worth the extra bit of time put into them, and a huge amount learned about proper shot workflow, with thanks to the guys in work for all the helpful tips and feedback.





Adequately Final Splined from Eoin Coakley on Vimeo.


Favourite Final Splined from Eoin Coakley on Vimeo.

Tuesday, 7 January 2014

Last chicken in Superquin

Looks like he just made it out in time, thankfully, they can do wonderful things with wigs these days. Tried animating this chicken, was tricky enough, different mechanics to a bipedal run. Turned out to be quite similar to the back legs of the horse.


Thursday, 2 January 2014

Merry New Year!

Back today after a not quite long enough Christmas break, never is though. I started animating this on the day of our Christmas party, a common enough sight all around the world at this time of year. Now that the hangover has subsided I've polished the animation off and done some basic lighting in the scene.