CGTalk > Software > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
Thread Closed share thread « Previous Thread | Next Thread »  
 
Thread Tools Search this Thread Display Modes
Old 07-19-2005, 12:26 AM   #1
erilaz
Stealthy Tea Monkey
 
erilaz's Avatar
portfolio
Martin Brennand
VFX Artist
Melbourne, Australia
 
Join Date: Jun 2002
Posts: 13,756
CgTalk Maxscript Challenge 006: "Object Photo Album"

CgTalk Maxscript Challenge 006: "Object Photo Album"

DESCRIPTION: Create a tool that focuses on each object in a scene and renders each object as a seperate image. For example, if there are three spheres in a scene you would end up with a folder containing three images, one of each object. You can either render the object or viewport snap it.

INTERMEDIATE SCRIPTERS: Embed the images in a HTML document and add information about each object (poly count, textures etc.)

ADVANCED SCRIPTERS: Compile the whole thing (scene, images and html document) into it's own folder or zip file, ready for "release". Consider this like a tool to keep track of finished max files in a development environment.

RULES:

  • Code from scratch. Try not to use pre-exisitng functions or plugins.
  • Show your script references, if any (eg. Looking at another script to assist you).
  • You are encouraged to ask for help where needed, but try to do it on your own. The maxscript reference is an invaluable resource.
  • Post your final script inside [CODE] tags (located on your posting toolbar).
  • Post all code into THIS thread.
  • Post the max version you coded in, plus any maxscript extensions you used. (Thanks galagast!)
  • Try to finish the challenge in a week. There is no definite time limit.
  • Voting will occur at the end of each 'month' (every 4 challenges).
NOTES: None this week... I feel it's pretty straightforward. If you don't know HTML, it's not too hard to learn, there's numerous sites on how to write simple code for this. Remember to vote for the first 4 challenges: http://www.cgtalk.com/showthread.php?t=257580
__________________
"There Really is No Secret"
Martin Brennand - mocha Product Manager - Imagineer Systems

Last edited by erilaz : 07-19-2005 at 12:30 AM.
 
Old 07-19-2005, 10:26 PM   #2
ofer_z
Frequenter
 
Join Date: Jun 2002
Posts: 234
this one appeared to be interesting to me, so here's my take on it:

Code:
try (destroyDialog ro_ContactSheet) catch() rollout ro_ContactSheet "Object Contact Sheet" ( -- Local Variable declerations -------------------------------------------------------------- local indent = "" local HTMLFilename = "" -- User Interface -------------------------------------------------------------- group "Output Folder: " ( radioButtons rbOutputFolder "" labels:#("Use the current max file folder.", "Use a custom folder:") align:#left columns:1 default:(if maxFilePath != "" then 1 else 2) edittext edOutputFolder "" fieldWidth:270 align:#left across:2 offset:[-8,0] button bnOutputFolderBrowse "..." width:18 height:16 align:#right offset:[3,0] ) group "Render Options: " ( spinner spOutputWidth "Output Size: Width:" fieldWidth:45 type:#integer range:[1, 9e5, renderWidth] align:#left across:2 spinner spOutputHeight "Height:" fieldWidth:45 type:#integer range:[1, 9e5, renderHeight] align:#left offset:[20,0] label lblImageType "Image Type: " align:#left across:2 offset:[0,3] dropDownList ddlImageType "" width:50 items:#("jpg", "png") default:1 align:#left offset:[-80,0] colorPicker cpBGColor "Background Color: " align:#right offset:[0,-26] color:backgroundColor spinner spCameraFOV "Camera FOV: " fieldWidth:40 range:[1.0, 179., 30.] type:#float align:#left offset:[0,3] radioButtons rbLights "Lights:" labels:#("Use Scene Lights", "Use Internal Light Rig") default:2 align:#left columns:1 ) group "Zip Files: " ( checkbox cbEnableZip "Zip files into file:" align:#left edittext edZipFile "" fieldWidth:250 align:#left across:2 offset:[12,0] enabled:cbEnableZip.checked button bnZipFileBrowse "..." width:18 height:16 align:#right offset:[3,0] enabled:cbEnableZip.checked checkbox cbZipDeleteFiles "Delete contact sheet files after zipping." align:#left enabled:cbEnableZip.checked button bnZipOpenFolder "Open Zip File Folder" width:290 height:20 enabled:(doesFileExist edZipFile.text) ) group "Progress: " ( label lblProgTotal "Processed/Total number of objects: " align:#left label lblProgExported "Actual number of exported objects: " align:#left progressBar pbProgress "" ) button bnGo "Create Contact Sheet" width:300 height:25 enabled:(rbOutputFolder.state == 1) button bnView "View Contact Sheet" width:145 height:25 enabled:false align:#left across:2 offset:[-8,0] button bnOpenFolder "Open HTML Folder" width:145 height:25 enabled:false align:#right offset:[8,0] -- General Functions -------------------------------------------------------------- fn getVisibleObjects = ( for o in objects where not o.isHidden collect o ) fn getEnabledLights = ( for l in lights where (not isKindOf l TargetObject and l.baseObject.on) collect l ) fn getNumVerts obj = ( obj.mesh.verts.count ) fn getNumFaces obj = ( try ( obj.faces.count ) catch ( obj.mesh.faces.count ) ) fn getObjectTextueFiles obj = ( local tex = #() if obj != undefined then ( for i = 1 to obj.numSubs do ( if isKindOf obj[i] Bitmaptexture then append tex obj[i].filename join tex (getObjectTextueFiles obj[i]) ) ) tex ) -- HTML Writing Functions -------------------------------------------------------------- fn incIndent &i = i += "\t" fn decIndent &i = ( if i.count > 0 then i = subString i 1 (i.count - 1) else "" ) fn writeObjTexturesHTML HTMLFileHandle obj photoName &indent = ( local tex = getObjectTextueFiles obj.material if tex.count > 0 then ( incIndent &indent format "%<b>Texture Files:</b><br />\n" indent to:HTMLFileHandle format "%<ul>\n" indent to:HTMLFileHandle incIndent &indent for t in tex do format "%<li>%</li>\n" indent t to:HTMLFileHandle decIndent &indent format "%</ul>\n" indent to:HTMLFileHandle decIndent &indent ) ) fn writeObjHTMLCode HTMLFileHandle obj photoName &indent = ( try ( format "%<tr>\n" indent to:HTMLFileHandle incIndent &indent format "%<td>\n" indent to:HTMLFileHandle incIndent &indent format "%<img src=\"%\" style=\"border: 1px solid black; display: inline;\" alt=\"%\" />\n" indent photoName obj.name to:HTMLFileHandle decIndent &indent format "%</td>\n" indent to:HTMLFileHandle format "%<td valign=\"top\" align=\"left\" width=\"100\%\">\n" indent to:HTMLFileHandle incIndent &indent format "%<b>Object Name:</b>%<br />\n" indent obj.name to:HTMLFileHandle format "%<b>Vertices:</b>%<br />\n" indent (getNumVerts obj) to:HTMLFileHandle format "%<b>Faces:</b>%<br />\n" indent (getNumFaces obj) to:HTMLFileHandle writeObjTexturesHTML HTMLFileHandle obj photoName &indent decIndent &indent format "%</td>\n" indent to:HTMLFileHandle decIndent &indent format "%</tr>\n" indent to:HTMLFileHandle -- create a divider format "%<tr>\n" indent to:HTMLFileHandle incIndent &indent format "%<td colspan=\"2\">\n" indent to:HTMLFileHandle incIndent &indent format "%<hr />\n" indent photoName obj.name to:HTMLFileHandle decIndent &indent format "%</td>\n" indent to:HTMLFileHandle decIndent &indent format "%</tr>\n" indent to:HTMLFileHandle )catch() ) fn writeHTMLHeaderCode HTMLFileHandle &indent = ( try ( format "%<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" indent to:HTMLFileHandle format "%<html>\n" indent to:HTMLFileHandle format "%<head>\n" indent to:HTMLFileHandle incIndent &indent format "%<title>contactSheet - 3DS Max Object Contact Sheet</title>\n" indent to:HTMLFileHandle -- write the styles format "%<style type=\"text/stylesheet\">\n" indent to:HTMLFileHandle incIndent &indent format "%hr {\n" indent to:HTMLFileHandle incIndent &indent format "%height: 1px;\n" indent to:HTMLFileHandle format "%color: Gray;\n" indent to:HTMLFileHandle format "%border-style: solid;\n" indent to:HTMLFileHandle decIndent &indent format "%}\n" indent to:HTMLFileHandle decIndent &indent format "%</style>\n" indent to:HTMLFileHandle decIndent &indent format "%</head>\n" indent to:HTMLFileHandle format "%<body>\n" indent to:HTMLFileHandle incIndent &indent format "%<table width=\"95\%\" align=\"center\" style=\"border: 2px solid black;\">\n" indent to:HTMLFileHandle incIndent &indent )catch() ) fn writeHTMLFooterCode HTMLFileHandle &indent = ( try ( decIndent &indent format "%</table>\n" indent to:HTMLFileHandle decIndent &indent format "%</body>\n" indent to:HTMLFileHandle decIndent &indent format "%</html>\n" indent to:HTMLFileHandle )catch() ) -- Render Functions -------------------------------------------------------------- -- taken form the maxscript help, and slightly modified. fn GetVFOV fov renderSize:[renderWidth, renderHeight] = ( local r_aspect=(renderSize.x as float)/renderSize.y 2.0*atan(tan(fov/2.0)/r_aspect) ) fn genContactSheetCam obj fov renderSize = ( -- create the temp camera local cam = freeCamera name:"ContactSheetCam" fov:fov -- move and rotate the camera to match the object's transformation cam.transform = obj.transform cam.pos = obj.center in coordsys cam rotate cam (eulerAngles 90 0 0) -- calculate the distance needed to fit the entire object local bBoxSize = (obj.max - obj.min) * 1.1 local distWidth = (bBoxSize.x / 2.) / tan (fov / 2.) local distHeight = (bBoxSize.y / 2.) / tan ((getVFOV fov renderSize:renderSize) / 2.) local dist = amax (abs distWidth) (abs distHeight) -- move the camera back so it sees the whole object. in coordsys cam cam.pos.z += dist -- return the camera object cam ) fn genObjRender obj renderSize fov useSceneLights:false = ( -- create the temp camera object. local camObj = genContactSheetCam obj fov renderSize -- if we're not going to use the scene lights, create the temp light rig if not useSceneLights then ( local keyLight = omniLight name:"ContactSheetTempLight" color:white multiplier:1.0 local fillLight = omniLight name:"ContactSheetTempLight" color:white multiplier:0.5 in coordsys camObj ( local dist = distance camObj.pos obj.center keyLight.pos = [dist, dist, 0] fillLight.pos = [-dist, -dist, 0] ) ) -- render the object local rend = render camera:camObj outputSize:renderSize renderhiddenobjects:false vfb:false -- delete the camera delete camObj -- delete the temp lights if isValidNode keyLight then delete keyLight if isValidNode fillLight then delete fillLight -- return the rendered bitmap rend ) -- contactSheet Functions -------------------------------------------------------------- -- this function creates a contact sheet entry for a single object. -- it first renders the object, then generates the HTML code. fn contactSheetObj obj outputDir HTMLFileHandle renderSize fov useSceneLights:false imgType:"jpg" mode:#render = ( -- check if the object is a geometry object, if not quit the fn. if not (isValidNode obj) or not (isKindOf obj GeometryClass) or (isKindOf obj targetObject) then return false -- store the hidden state of the object to restore it later. local objIsHidded = obj.isHidden -- make sure the object is not hidden obj.isHidden = false local rend = bitmap 30 30 color:black case mode of ( #render: rend = genObjRender obj renderSize fov useSceneLights:useSceneLights ) -- end case -- save the bitmap local photoName = obj.name + "." + imgType rend.filename = outputDir + photoName save rend writeObjHTMLCode HTMLFileHandle obj photoName &indent -- restore the object hidden state obj.isHidden = objIsHidded -- return true true ) -- This function loops through all objects and calls the single object -- contact sheet to do the actual job. -- This function also updates the UI, and gets the parameters set in -- the UI and passes them on. fn contactSheet = ( -- declare output name and directory variables. local outputName = if maxFileName == "" then "Untitled" else (getFilenameFile maxFileName) local outputDir = if rbOutputFolder.state == 2 then edOutputFolder.text else maxFilePath if outputDir[outputDir.count] != "\\" and outputDir[outputDir.count] != "/" then outputDir += "\\" outputDir += outputName + "\\" makedir outputDir local HTMLFileName = outputDir + outputName + ".html" -- create the HTML file local HTMLFileHandle = createFile HTMLFileName -- if the HTML file was not created, abort. if HTMLFileHandle == undefined then return() -- Write the HTML headers writeHTMLHeaderCode HTMLFileHandle &indent disableSceneRedraw() -- store the scene state for restoring later. local renderSize = [spOutputWidth.value, spOutputHeight.value] local visObjs = getVisibleObjects() local enabledLights = getEnabledLights() local BGCol = backgroundColor backgroundColor = cpBGColor.color -- turn off scene lights and hide all objects. if rbLights.state != 1 then ( for l in enabledLights do l.baseObject.on = off ) hide objects -- create the contact sheet elements for each object. local counter = 0 -- actual number of objects that were processed local i = 0. -- a counter for the progress bar local imgType = ddlImageType.selected local useSceneLights = (rbLights.state == 1) local fov = spCameraFOV.value for o in objects do ( try ( if (contactSheetObj o outputDir HTMLFileHandle renderSize fov useSceneLights:useSceneLights imgType:imgType mode:#render) then counter += 1 ) catch(print "error") i += 1. lblProgTotal.text = "Processed/Total number of objects: " + (i as integer) as string + "/" + (objects.count) as string pbProgress.value = i / (objects.count as float) * 100. ) lblProgExported.text = "Actual number of exported objects: " + counter as string -- write the HTML footers writeHTMLFooterCode HTMLFileHandle &indent -- close the HTML file close HTMLFileHandle -- restore scene to original state. for l in enabledLights do l.baseObject.on = on unHide visObjs backgroundColor = BGCol enableSceneRedraw() -- return the HTML filename HTMLFileName ) -- Zip Functions ------------------------------------------------------------------- -- archives all the files in dir into zipFilename using maxzip.exe fn zipFiles dir zipFilename = ( if zipFilename == "" then return false if dir[dir.count] != "\\" and dir[dir.count] != "/" then dir += "\\" local files = getFiles (dir + "*") if not doesFileExist dir or files.count == 0 then return false -- generate a file with the list of files to be archived local listFilename = sysInfo.tempDir + "~maxzipTempList" + timeStamp() as string + ".lst" local f = createFile listFilename if f == undefined then return false for i in files do format "%\n" i to:f flush f close f -- archive the files into the zip local curDir = sysInfo.currentDir local zipUtil = getDir #maxRoot + "maxzip.exe" local zipFile = getFileNameFile zipFilename + getFileNameType zipFilename local cmd = "" as stringStream sysInfo.currentDir = getFilenamePath zipFilename format "\"%\" % @%" zipUtil zipFile listFilename to:cmd local archive = dosCommand cmd sysInfo.currentDir = curDir -- delete the temporary list file deleteFile listFilename -- return true on success false on failure archive == 0 ) -- deletes all files in a give folder fn deleteFiles dir = ( if dir[dir.count] != "\\" and dir[dir.count] != "/" then dir += "\\" for f in getFiles (dir + "*") do deleteFile f ) -- UI Functions ------------------------- -- This function is responsible for all the UI elements' update such as enabling/disabling etc. fn updateUI = ( local f = if rbOutputFolder.state == 1 then maxFilePath else edOutputFolder.text if f != "" and f[f.count] != "\\" and f[f.count] != "/" then f += "\\" bnGo.enabled = doesFileExist f edOutputFolder.enabled = rbOutputFolder.state == 2 bnOutputFolderBrowse.enabled = rbOutputFolder.state == 2 edZipFile.enabled = cbEnableZip.checked bnZipFileBrowse.enabled = cbEnableZip.checked cbZipDeleteFiles.enabled = cbEnableZip.checked bnZipOpenFolder.enabled = doesFileExist (getFilenamePath edZipFile.text) bnView.enabled = doesFileExist HTMLFilename bnOpenFolder.enabled = doesFileExist (getFilenamePath HTMLFilename) ) -- Event Handlers ----------------------------------------------------------------------- on rbOutputFolder changed state do ( if state == 1 then ( if maxFilePath == "" then ( messageBox "It appears the current max file has never been save.\nPlease save it before using this option." rbOutputFolder.state = 2 state = 2 ) ) updateUI() ) on edOutputFolder changed txt do ( updateUI() ) on bnOutputFolderBrowse pressed do ( local f = getSavePath() if f != undefined then ( edOutputFolder.text = f updateUI() ) ) on cbEnableZip changed state do ( updateUI() ) on edZipFile changed txt do ( updateUI() ) on bnZipFileBrowse pressed do ( local f = getSaveFilename filename:(maxFilePath + getFilenameFile maxFileName + ".zip") types:"ZIP Files (*.zip)|*.zip|All Files (*.*)|*.*" if f != undefined then ( edZipFile.text = f updateUI() ) ) on bnZipOpenFolder pressed do ( if doesFileExist (getFilenamePath edZipFile.text) then shellLaunch (getFilenamePath edZipFile.text) "" ) on bnGo pressed do ( HTMLFilename = contactSheet() local dir = getFilenamePath HTMLFilename if cbEnableZip.checked then ( local zipped = zipFiles dir edZipFile.text if zipped then ( if cbZipDeleteFiles.checked and (queryBox "Delete all files in the contact sheet folder?\nThis cannot be undone!") then deleteFiles dir ) else ( messageBox "The zipping of the files failed." ) ) updateUI() ) on bnView pressed do ( shellLaunch HTMLFilename "" ) on bnOpenFolder pressed do ( shellLaunch (getFilenamePath HTMLFilename) "" ) on ro_ContactSheet open do ( updateUI() ) )-- end of ro_ContactSheet createDialog ro_ContactSheet width:310


tested only on max 7


cheers,
o
__________________
--/* Commenting out the comments */--
Forget About Love

= undefined
 
Old 07-20-2005, 09:39 AM   #3
erilaz
Stealthy Tea Monkey
 
erilaz's Avatar
portfolio
Martin Brennand
VFX Artist
Melbourne, Australia
 
Join Date: Jun 2002
Posts: 13,756
Wow, great work ofer_z! I like the handling of render styles and the easy access to the html sheet afterwards. Very well done!
__________________
"There Really is No Secret"
Martin Brennand - mocha Product Manager - Imagineer Systems
 
Old 07-20-2005, 08:11 PM   #4
yoni-cohen
Know-it-All
 
yoni-cohen's Avatar
Yoni Cohen
Co. Founder
snowball | VFX
Tel-Aviv, Israel
 
Join Date: Aug 2002
Posts: 347
Wow

Hey ofer I thought you wanted to leave the 3d arena, I liked it!!
very well done.
 
Old 07-21-2005, 11:41 AM   #5
ofer_z
Frequenter
 
Join Date: Jun 2002
Posts: 234
here's an improved version, it allows to select the camera angle to render from.

Code:
--************************************************** *********************************** --* Object Contact Sheet --* By Ofer Zelichover --* www.oferz.com --* --* Created for a CGTalk MaxScript Challenge. 21/7/2005 --************************************************** *********************************** try (destroyDialog ro_ContactSheet) catch() rollout ro_ContactSheet "Object Contact Sheet" ( -- Local Variable declerations -------------------------------------------------------------- local indent = "" local HTMLFilename = "" -- User Interface -------------------------------------------------------------- group "Output Folder: " ( radioButtons rbOutputFolder "" labels:#("Use the current max file folder.", "Use a custom folder:") align:#left columns:1 default:(if maxFilePath != "" then 1 else 2) edittext edOutputFolder "" fieldWidth:270 align:#left across:2 offset:[-8,0] button bnOutputFolderBrowse "..." width:18 height:16 align:#right offset:[3,0] ) group "Render Options: " ( spinner spOutputWidth "Output Size: Width:" fieldWidth:45 type:#integer range:[1, 9e5, renderWidth] align:#left across:2 spinner spOutputHeight "Height:" fieldWidth:45 type:#integer range:[1, 9e5, renderHeight] align:#left offset:[20,0] label lblImageType "Image Type: " align:#left across:2 offset:[0,3] dropDownList ddlImageType "" width:50 items:#("jpg", "png") default:1 align:#left offset:[-80,0] colorPicker cpBGColor "Background Color: " height:18 fieldWidth:25 align:#right offset:[0,-26] color:backgroundColor spinner spCameraFOV "Camera FOV: " fieldWidth:40 range:[1.0, 179., 30.] type:#float align:#left offset:[0,3] radioButtons rbCameraAngle "Camera Angle:" labels:#("Front", "Top", "Side", "Perspective", "All") default:1 align:#left columns:3 offset:[0,3] radioButtons rbLights "Lights:" labels:#("Use Scene Lights", "Use Internal Light Rig") default:2 align:#left columns:1 offset:[0,3] ) group "Zip Files: " ( checkbox cbEnableZip "Zip files into file:" align:#left edittext edZipFile "" fieldWidth:250 align:#left across:2 offset:[12,0] enabled:cbEnableZip.checked button bnZipFileBrowse "..." width:18 height:16 align:#right offset:[3,0] enabled:cbEnableZip.checked checkbox cbZipDeleteFiles "Delete contact sheet files after zipping." align:#left enabled:cbEnableZip.checked button bnZipOpenFolder "Open Zip File Folder" width:290 height:20 enabled:(doesFileExist edZipFile.text) ) group "Progress: " ( label lblProgTotal "Processed/Total number of objects: " align:#left label lblProgExported "Actual number of exported objects: " align:#left progressBar pbProgress "" ) button bnGo "Create Contact Sheet" width:300 height:25 enabled:(rbOutputFolder.state == 1) button bnView "View Contact Sheet" width:145 height:25 enabled:false align:#left across:2 offset:[-8,0] button bnOpenFolder "Open HTML Folder" width:145 height:25 enabled:false align:#right offset:[8,0] -- General Functions -------------------------------------------------------------- fn getVisibleObjects = ( for o in objects where not o.isHidden collect o ) fn getEnabledLights = ( for l in lights where (not isKindOf l TargetObject and l.baseObject.on) collect l ) fn getNumVerts obj = ( obj.mesh.verts.count ) fn getNumFaces obj = ( try ( obj.faces.count ) catch ( obj.mesh.faces.count ) ) fn getObjectTextueFiles obj = ( local tex = #() if obj != undefined then ( for i = 1 to obj.numSubs do ( if isKindOf obj[i] Bitmaptexture then append tex obj[i].filename join tex (getObjectTextueFiles obj[i]) ) ) tex ) -- HTML Writing Functions -------------------------------------------------------------- fn incIndent &i = i += "\t" fn decIndent &i = ( if i.count > 0 then i = subString i 1 (i.count - 1) else "" ) fn writeObjTexturesHTML HTMLFileHandle obj photoName &indent = ( local tex = getObjectTextueFiles obj.material if tex.count > 0 then ( incIndent &indent format "%<b>Texture Files:</b><br />\n" indent to:HTMLFileHandle format "%<ul>\n" indent to:HTMLFileHandle incIndent &indent for t in tex do format "%<li>%</li>\n" indent t to:HTMLFileHandle decIndent &indent format "%</ul>\n" indent to:HTMLFileHandle decIndent &indent ) ) fn writeObjHTMLCode HTMLFileHandle obj photoName &indent = ( try ( format "%<tr>\n" indent to:HTMLFileHandle incIndent &indent format "%<td>\n" indent to:HTMLFileHandle incIndent &indent format "%<img src=\"%\" style=\"border: 1px solid black; display: inline;\" alt=\"%\" />\n" indent photoName obj.name to:HTMLFileHandle decIndent &indent format "%</td>\n" indent to:HTMLFileHandle format "%<td valign=\"top\" align=\"left\" width=\"100\%\">\n" indent to:HTMLFileHandle incIndent &indent format "%<b>Object Name:</b>%<br />\n" indent obj.name to:HTMLFileHandle format "%<b>Vertices:</b>%<br />\n" indent (getNumVerts obj) to:HTMLFileHandle format "%<b>Faces:</b>%<br />\n" indent (getNumFaces obj) to:HTMLFileHandle writeObjTexturesHTML HTMLFileHandle obj photoName &indent decIndent &indent format "%</td>\n" indent to:HTMLFileHandle decIndent &indent format "%</tr>\n" indent to:HTMLFileHandle -- create a divider format "%<tr>\n" indent to:HTMLFileHandle incIndent &indent format "%<td colspan=\"2\">\n" indent to:HTMLFileHandle incIndent &indent format "%<hr />\n" indent photoName obj.name to:HTMLFileHandle decIndent &indent format "%</td>\n" indent to:HTMLFileHandle decIndent &indent format "%</tr>\n" indent to:HTMLFileHandle )catch() ) fn writeHTMLHeaderCode HTMLFileHandle &indent = ( try ( format "%<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" indent to:HTMLFileHandle format "%<html>\n" indent to:HTMLFileHandle format "%<head>\n" indent to:HTMLFileHandle incIndent &indent format "%<title>contactSheet - 3DS Max Object Contact Sheet</title>\n" indent to:HTMLFileHandle -- write the styles format "%<style type=\"text/stylesheet\">\n" indent to:HTMLFileHandle incIndent &indent format "%hr {\n" indent to:HTMLFileHandle incIndent &indent format "%height: 1px;\n" indent to:HTMLFileHandle format "%color: Gray;\n" indent to:HTMLFileHandle format "%border-style: solid;\n" indent to:HTMLFileHandle decIndent &indent format "%}\n" indent to:HTMLFileHandle decIndent &indent format "%</style>\n" indent to:HTMLFileHandle decIndent &indent format "%</head>\n" indent to:HTMLFileHandle format "%<body>\n" indent to:HTMLFileHandle incIndent &indent format "%<table width=\"95\%\" align=\"center\" style=\"border: 2px solid black;\">\n" indent to:HTMLFileHandle incIndent &indent )catch() ) fn writeHTMLFooterCode HTMLFileHandle &indent = ( try ( decIndent &indent format "%</table>\n" indent to:HTMLFileHandle decIndent &indent format "%</body>\n" indent to:HTMLFileHandle decIndent &indent format "%</html>\n" indent to:HTMLFileHandle )catch() ) -- Render Functions -------------------------------------------------------------- -- taken form the maxscript help, and slightly modified. fn GetVFOV fov renderSize:[renderWidth, renderHeight] = ( local r_aspect=(renderSize.x as float)/renderSize.y 2.0*atan(tan(fov/2.0)/r_aspect) ) fn genContactSheetCam obj fov renderSize view:#front = ( -- create the temp camera local cam = freeCamera name:"ContactSheetCam" fov:fov -- move and rotate the camera to match the object's transformation cam.transform = obj.transform cam.pos = obj.center local angs = #() case view of ( #front: angs = #(eulerAngles 90 0 0) #side: angs = #(eulerAngles 0 90 0, eulerAngles 0 0 90) #top: angs = #(eulerAngles 0 0 0) #persp: angs = #(eulerAngles 45 0 45) default: angs = (eulerAngles 90 0 0) ) in coordsys cam ( for a in angs do rotate cam a ) -- calculate the distance needed to fit the entire object local bBoxSize = (obj.max - obj.min) * 1.1 local distWidth = (bBoxSize.x / 2.) / tan (fov / 2.) local distHeight = (bBoxSize.y / 2.) / tan ((getVFOV fov renderSize:renderSize) / 2.) local dist = amax (abs distWidth) (abs distHeight) -- move the camera back so it sees the whole object. in coordsys cam cam.pos.z += dist -- return the camera object cam ) fn genObjRender obj renderSize fov useSceneLights:false view:#front = ( -- create the temp camera object. local camObj = genContactSheetCam obj fov renderSize view:view -- if we're not going to use the scene lights, create the temp light rig if not useSceneLights then ( local keyLight = omniLight name:"ContactSheetTempLight" color:white multiplier:1.0 local fillLight = omniLight name:"ContactSheetTempLight" color:white multiplier:0.5 in coordsys camObj ( local dist = distance camObj.pos obj.center keyLight.pos = [dist, dist, 0] fillLight.pos = [-dist, -dist, 0] ) ) -- render the object local rend = render camera:camObj outputSize:renderSize renderhiddenobjects:false vfb:false -- delete the camera delete camObj -- delete the temp lights if isValidNode keyLight then delete keyLight if isValidNode fillLight then delete fillLight -- return the rendered bitmap rend ) -- combine 4 images into one image. fn combineImages images rendSize = ( -- create a compositeTexture map that will do the compositing local comp = CompositeTexturemap name:"tempComp" local filenames = #() for i = 1 to images.count do ( -- to be able to use a bitmap value as a bitmaptexture the bitmap must first be saved. -- so, save the bitmap to a temporary file. images[i].filename = sysInfo.tempDir + "~tempCompBitmap" + i as string + "_" + timeStamp() as string + ".png" save images[i] -- append the temp bitmap filename to a list, so it can be deleted later. append filenames images[i].filename -- create a bitmapTexture map for the image local b = Bitmaptexture name:("tempBitmap" + i as string) bitmap:images[i] filtering:1 -- and set some parameters. the compositing is done by setting the UV tiling values to 2 -- so the image is going to be half the size of the final image. b.coords.U_Mirror = false b.coords.V_Mirror = false b.coords.U_Tile = false b.coords.V_Tile = false b.coords.U_Tiling = 2. b.coords.V_Tiling = 2. b.coords.U_Offset = 0.25 * (if (mod i 2) == 0 then 1 else -1) b.coords.V_Offset = 0.25 * (if i > 2 then -1 else 1) -- add the bitmapTexture to the composite map list comp.mapList[i] = b ) -- delete the temp files for f in filenames do deleteFile f -- render the composite texture and return the result rend = renderMap comp size:rendSize display:false ) fn genMultiRender obj renderSize fov useSceneLights:false = ( local rendSize = renderSize / 2 local images = #() -- generate image for each of the 4 views append images (genObjRender obj rendSize fov useSceneLights:useSceneLights view:#top) append images (genObjRender obj rendSize fov useSceneLights:useSceneLights view:#front) append images (genObjRender obj rendSize fov useSceneLights:useSceneLights view:#side) append images (genObjRender obj rendSize fov useSceneLights:useSceneLights view:#persp) -- return the combined image combineImages images renderSize ) -- contactSheet Functions -------------------------------------------------------------- -- this function creates a contact sheet entry for a single object. -- it first renders the object, then generates the HTML code. fn contactSheetObj obj outputDir HTMLFileHandle renderSize fov useSceneLights:false imgType:"jpg" mode:#render view:#front= ( -- check if the object is a geometry object, if not quit the fn. if not (isValidNode obj) or not (isKindOf obj GeometryClass) or (isKindOf obj targetObject) then return false -- store the hidden state of the object to restore it later. local objIsHidded = obj.isHidden -- make sure the object is not hidden obj.isHidden = false local rend = bitmap 30 30 color:black case mode of ( #render: rend = genObjRender obj renderSize fov useSceneLights:useSceneLights view:view #multiRender: rend = genMultiRender obj renderSize fov useSceneLights:useSceneLights ) -- end case -- save the bitmap local photoName = obj.name + "." + imgType rend.filename = outputDir + photoName save rend writeObjHTMLCode HTMLFileHandle obj photoName &indent -- restore the object hidden state obj.isHidden = objIsHidded -- return true true ) -- This function loops through all objects and calls the single object -- contact sheet to do the actual job. -- This function also updates the UI, and gets the parameters set in -- the UI and passes them on. fn contactSheet = ( -- declare output name and directory variables. local outputName = if maxFileName == "" then "Untitled" else (getFilenameFile maxFileName) local outputDir = if rbOutputFolder.state == 2 then edOutputFolder.text else maxFilePath if outputDir[outputDir.count] != "\\" and outputDir[outputDir.count] != "/" then outputDir += "\\" outputDir += outputName + "\\" makedir outputDir local HTMLFileName = outputDir + outputName + ".html" -- create the HTML file local HTMLFileHandle = createFile HTMLFileName -- if the HTML file was not created, abort. if HTMLFileHandle == undefined then return() -- Write the HTML headers writeHTMLHeaderCode HTMLFileHandle &indent disableSceneRedraw() -- store the scene state for restoring later. local renderSize = [spOutputWidth.value, spOutputHeight.value] local visObjs = getVisibleObjects() local enabledLights = getEnabledLights() local BGCol = backgroundColor backgroundColor = cpBGColor.color -- turn off scene lights and hide all objects. if rbLights.state != 1 then ( for l in enabledLights do l.baseObject.on = off ) hide objects -- create the contact sheet elements for each object. local counter = 0 -- actual number of objects that were processed local i = 0. -- a counter for the progress bar local imgType = ddlImageType.selected local useSceneLights = (rbLights.state == 1) local view = case rbCameraAngle.state of (1:#front; 2:#top; 3:#side; 4:#persp; 5:#all) local mode = if rbCameraAngle.state == 5 then #multiRender else #render local fov = spCameraFOV.value lblProgTotal.text = "Processed/Total number of objects: 0" + "/" + (objects.count) as string pbProgress.value = 0. for o in objects do ( try ( if (contactSheetObj o outputDir HTMLFileHandle renderSize fov useSceneLights:useSceneLights imgType:imgType mode:mode view:view) then counter += 1 ) catch(print ("error (object:" + o.name + ")")) i += 1. lblProgTotal.text = "Processed/Total number of objects: " + (i as integer) as string + "/" + (objects.count) as string pbProgress.value = i / (objects.count as float) * 100. ) lblProgExported.text = "Actual number of exported objects: " + counter as string -- write the HTML footers writeHTMLFooterCode HTMLFileHandle &indent -- close the HTML file close HTMLFileHandle -- restore scene to original state. for l in enabledLights do l.baseObject.on = on unHide visObjs backgroundColor = BGCol enableSceneRedraw() -- return the HTML filename HTMLFileName ) -- Zip Functions ------------------------------------------------------------------- -- archives all the files in dir into zipFilename using maxzip.exe fn zipFiles dir zipFilename = ( if zipFilename == "" then return false if dir[dir.count] != "\\" and dir[dir.count] != "/" then dir += "\\" local files = getFiles (dir + "*") if not doesFileExist dir or files.count == 0 then return false -- generate a file with the list of files to be archived local listFilename = sysInfo.tempDir + "~maxzipTempList" + timeStamp() as string + ".lst" local f = createFile listFilename if f == undefined then return false for i in files do format "%\n" i to:f flush f close f -- archive the files into the zip local curDir = sysInfo.currentDir local zipUtil = getDir #maxRoot + "maxzip.exe" local zipFile = getFileNameFile zipFilename + getFileNameType zipFilename local cmd = "" as stringStream sysInfo.currentDir = getFilenamePath zipFilename format "\"%\" % @%" zipUtil zipFile listFilename to:cmd local archive = dosCommand cmd sysInfo.currentDir = curDir -- delete the temporary list file deleteFile listFilename -- return true on success false on failure archive == 0 ) -- deletes all files in a give folder fn deleteFiles dir = ( if dir[dir.count] != "\\" and dir[dir.count] != "/" then dir += "\\" for f in getFiles (dir + "*") do deleteFile f ) -- UI Functions ------------------------- -- This function is responsible for all the UI elements' update such as enabling/disabling etc. fn updateUI = ( local f = if rbOutputFolder.state == 1 then maxFilePath else edOutputFolder.text if f != "" and f[f.count] != "\\" and f[f.count] != "/" then f += "\\" bnGo.enabled = doesFileExist f edOutputFolder.enabled = rbOutputFolder.state == 2 bnOutputFolderBrowse.enabled = rbOutputFolder.state == 2 edZipFile.enabled = cbEnableZip.checked bnZipFileBrowse.enabled = cbEnableZip.checked cbZipDeleteFiles.enabled = cbEnableZip.checked bnZipOpenFolder.enabled = doesFileExist (getFilenamePath edZipFile.text) bnView.enabled = doesFileExist HTMLFilename bnOpenFolder.enabled = doesFileExist (getFilenamePath HTMLFilename) ) -- Event Handlers ----------------------------------------------------------------------- on rbOutputFolder changed state do ( if state == 1 then ( if maxFilePath == "" then ( messageBox "It appears the current max file has never been save.\nPlease save it before using this option." rbOutputFolder.state = 2 state = 2 ) ) updateUI() ) on edOutputFolder changed txt do ( updateUI() ) on bnOutputFolderBrowse pressed do ( local f = getSavePath() if f != undefined then ( edOutputFolder.text = f updateUI() ) ) on cbEnableZip changed state do ( updateUI() ) on edZipFile changed txt do ( updateUI() ) on bnZipFileBrowse pressed do ( local f = getSaveFilename filename:(maxFilePath + getFilenameFile maxFileName + ".zip") types:"ZIP Files (*.zip)|*.zip|All Files (*.*)|*.*" if f != undefined then ( edZipFile.text = f updateUI() ) ) on bnZipOpenFolder pressed do ( if doesFileExist (getFilenamePath edZipFile.text) then shellLaunch (getFilenamePath edZipFile.text) "" ) on bnGo pressed do ( bnGo.enabled = false HTMLFilename = contactSheet() local dir = getFilenamePath HTMLFilename if cbEnableZip.checked then ( local zipped = zipFiles dir edZipFile.text if zipped then ( if cbZipDeleteFiles.checked and (queryBox "Delete all files in the contact sheet folder?\nThis cannot be undone!") then deleteFiles dir ) else ( messageBox "The zipping of the files failed." ) ) updateUI() ) on bnView pressed do ( shellLaunch HTMLFilename "" ) on bnOpenFolder pressed do ( shellLaunch (getFilenamePath HTMLFilename) "" ) on ro_ContactSheet open do ( updateUI() ) )-- end of ro_ContactSheet createDialog ro_ContactSheet width:310


again, max 7


Quote:
Originally Posted by yoni-cohen
Hey ofer I thought you wanted to leave the 3d arena, I liked it!!
very well done.

LOL. I though so too....
I guess I'm too lazy to do anything about it, and I'm getting a bit bored


cheers,
o
__________________
--/* Commenting out the comments */--
Forget About Love

= undefined
 
Old 07-21-2005, 03:40 PM   #6
yoni-cohen
Know-it-All
 
yoni-cohen's Avatar
Yoni Cohen
Co. Founder
snowball | VFX
Tel-Aviv, Israel
 
Join Date: Aug 2002
Posts: 347
so ofer does it mean you are ready to work (join us)?
we might use another scripter its getting busy
 
Old 07-21-2005, 03:55 PM   #7
yoni-cohen
Know-it-All
 
yoni-cohen's Avatar
Yoni Cohen
Co. Founder
snowball | VFX
Tel-Aviv, Israel
 
Join Date: Aug 2002
Posts: 347
man it is sweet

I would add an option to break it into groups by hierarchy or skin etc` so that it would be more production worthy but it is so cool non the less
 
Old 07-21-2005, 03:55 PM   #8
CGTalk Moderation
Expert
CGTalk Forum Leader
 
Join Date: Sep 2003
Posts: 1,066,478
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
__________________
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
 
Thread Closed share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 05:15 PM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.