3ds Max Mayhemhttp://area.autodesk.com/Topics of interest to people using and extending 3ds Max by Christopher Diggins, principal software developer at Autodesk.Thu, 05 May 2016 00:59:49 UTCMax Creation Graph: The Year in ReviewChristopher Diggins<h2>MCG &ndash; The Year in Review</h2> <p>I can't believe it's <a href="/blogs/max/introducing-3ds-max-2017"><strong>time for 3ds Max 2017 already</strong></a>!&nbsp;<span style="line-height: 1.5em;">It&rsquo;s been an exciting year for the MCG team. The <a href="/blogs/chris/introducing-max-creation-graphs">first <strong>release of the Max Creation Graph</strong></a> in April of last year a very positive reception from the 3ds Max user base, and over the year many people have created some pretty impressive tools.</span></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCGUserTools.jpg" width="1053" height="685" /></span></p> <h3><span style="line-height: 1.5em;">What&rsquo;s New in MCG in 3ds Max 2017</span></h3> <p><span style="line-height: 1.5em;">Most of what is new in MCG in 3ds Max 2017 is the cumulative result of the previous work we released to Subscription customers via the two Extension releases. One feature only in 3ds Max 2017 worth calling are two new random number operators: <em>RandInt</em> and <em>RandFloat</em>. These are fast stateless random number generators that can be used safely from within a ParallelMap or ParallelCombine, to generate consistent random numbers. Thanks to Robert Bridson from the Bifrost team for his help with that! &nbsp;</span></p> <p>When we first released MCG we only provided supported for Geometry, Modifier, and MAXScript utility plug-ins. 3ds Max 2017 supports produce animation controllers and spline primitive objects. We have also started to "eat our own dogfood" and now ship several tools with 3ds Max developed with MCG including some animation controllers, CFD visualization tools, and a sample "donut" spline object. These are not intended as tutorials, but if you are interested in looking under the hood you can find the new MCG tools under &lt;maxroot&gt;\MaxCreationGraph\Tools.&nbsp;&nbsp;</p> <p>Along with the new plug-in types several new parameter types have been added: Node Array, Single (floating point) Array, Vector3, Color, Asset, String, and a Signal. These enable you to create more varied UI for your tools without having to resort to MAXScript. <span style="line-height: 1.5em;">Several new operators were also added to MCG, including the ability create Bullet Physics simulations, reading and writing of OpenVDB files, and several operators for working with Spline objects.</span></p> <p>We will be posting a more detailed technical document about the new features in MCG for 3ds Max 2017 on <strong><a href="/blogs/mcgblog">The Max Creation Graph Blog</a></strong> in the next few days, so stay posted.&nbsp;</p> <h3>MCG Tools on CreativeMarket.com</h3> <p>One noteworthy development for 3D artists this year was when <strong><a href="http://creativemarket.com/blog/2015/08/11/creative-market-goes-3d">CreativeMarket.com announced support for artists to buy and sell 3D assets</a></strong>. Among the many different kinds of <a href="https://creativemarket.com/apps/3dsmax"><strong>3ds Max resources on CreativeMarket.com</strong></a> we are also seeing <strong><a href="https://creativemarket.com/tag/mcg">MCG tools starting to appear </a></strong>as well.&nbsp;</p> <h3>MCG Group on Facebook</h3> <p>In my opinion, one of the most important developments for MCG this year, was the creation of <strong><a href="https://www.facebook.com/groups/1611269852441897/">the MCG Facebook group</a></strong>, started less than a year ago, has now grown to over 6500 members, and is actively monitored by the MCG team. This is now *the* place to go to share MCG tools and techniques, and to ask questions from the pool of experts. In the file section of the page, you can find several MCG tools posted by our members.&nbsp;</p> <h3>MCG Tools on ScriptSpot</h3> <p>The popular scripting resource, ScriptSpot.com, now has a <a href="http://www.scriptspot.com/3ds-max/mcg"><strong>section dedicated just to MCG tools</strong></a> which by my last count had over 85 tools. Some of the most popular tools based on the votes on ScriptSpot (as of April 18th) are:&nbsp;</p> <p><strong>1. Voluminance MCG <span style="line-height: 1.5em;">by Jonathan de Blok&nbsp;</span></strong></p> <p><span style="line-height: 1.5em;"></span><a href="http://www.scriptspot.com/3ds-max/mcg/voluminance-mcg"><span style="line-height: 1.5em;">http://www.scriptspot.com/3ds-max/mcg/voluminance-mcg</span></a></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCGScriptSpotCaps/voluminance_splash.png" width="629" height="378" /></span></p> <p><strong>2. MCG 32BitPatternMaker&nbsp;<span style="line-height: 1.5em;">by Vusta</span></strong></p> <p><span style="line-height: 1.5em;"></span><a href="http://www.scriptspot.com/3ds-max/mcg/mcg-32bitpatternmaker"><span style="line-height: 1.5em;">http://www.scriptspot.com/3ds-max/mcg/mcg-32bitpatternmaker</span></a></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCGScriptSpotCaps/32bitpatternmaker2.jpg" width="638" height="484" /></span></p> <p><strong>3. MCG Rings&nbsp;<span style="line-height: 1.5em;">by Vusta</span></strong></p> <p><span style="line-height: 1.5em;"></span><a href="http://www.scriptspot.com/3ds-max/mcg/mcg-rings"><span style="line-height: 1.5em;">http://www.scriptspot.com/3ds-max/mcg/mcg-rings</span></a></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCGScriptSpotCaps/vu_rings.jpg" width="638" height="546" /></span></p> <p><strong>4. BUR_SpinScatter&nbsp;<span style="line-height: 1.5em;">by Bathyscaph</span></strong></p> <p><span style="line-height: 1.5em;"></span><a href="http://www.scriptspot.com/3ds-max/mcg/bur-spinscatter"><span style="line-height: 1.5em;">http://www.scriptspot.com/3ds-max/mcg/bur-spinscatter</span></a></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCGScriptSpotCaps/spinscatter_small.jpg" width="638" height="453" /></span></p> <p><strong><span style="line-height: 1.5em;">5. Vu_mcgRope&nbsp;</span><span style="line-height: 1.5em;">by Vusta</span></strong></p> <p><span style="line-height: 1.5em;"></span><span style="line-height: 1.5em;"><a href="http://www.scriptspot.com/3ds-max/mcg/vu-mcgrope">http://www.scriptspot.com/3ds-max/mcg/vu-mcgrope</a>&nbsp;</span><span style="line-height: 1.5em;">&nbsp;</span></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCGScriptSpotCaps/vu_mcgrope.jpg" width="307" height="540" /></span></p> <p><strong>6. Brick Wall Builder&nbsp;<span style="line-height: 1.5em;">by Alaa alnahlawi</span></strong></p> <p><a href="http://www.scriptspot.com/3ds-max/mcg/brick-wall-builder">http://www.scriptspot.com/3ds-max/mcg/brick-wall-builder</a></p> <p><img src="/userdata/blogs/chris/MCGScriptSpotCaps/brick_builder.jpg" width="768" height="432" /></p> <p><strong>7. SphereClone&nbsp;<span style="line-height: 1.5em;">by Ariel_G</span></strong></p> <p><a href="http://www.scriptspot.com/3ds-max/mcg/sphereclone"><span style="line-height: 1.5em;">http://www.scriptspot.com/3ds-max/mcg/sphereclone&nbsp;</span></a></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCGScriptSpotCaps/sphereclone.jpg" width="638" height="513" /></span></p> <h3>Acknowledgements</h3> <p>I want to thank everyone on the MCG Facebook page for their generous feedback, contributions, and encouragement. You are really helping guide us down an exciting journey that has only just begun. Everyone who has created a tool, given up in frustration, or even felt too overwhelmed to even try: we hear you and we will continue to work hard to respond to your needs. &nbsp;</p> <p>I also want to thank everyone on the 3ds Max team for their hard work in helping to make MCG what it is today, for providing an amazing tool to build on, and for participating in a vision for what we can do for our users now and in the future. &nbsp;</p> <h3>Special Thanks</h3> <p>I want to give a special call out to a couple people who really stood out this year for their contributions to the MCG year.&nbsp;</p> <h3>Vu Nguyen aka Vusta aka Vustarama</h3> <p>Vu has become the most prolific creator of MCG tools. He created over 60 of the tools on ScriptSpot.com and has been a huge part of the Facebook group success, helping answer countless questions. To be inspired check out some of Vu's creations check out the following:&nbsp;</p> <ul> <li><span style="line-height: 1.5em;"><a href="https://www.youtube.com/user/vustarama">Vu&rsquo;s videos on YouTube</a>:&nbsp;</span></li> <li><span style="line-height: 1.5em;"><a href="http://www.scriptspot.com/3ds-max/mcg/sort-top?search=vusta">Vu&rsquo;s free tools on ScriptSpot</a> &nbsp;</span></li> <li><span style="line-height: 1.5em;"><a href="http://creativemarket.com/vusta">Vu&rsquo;s store on CreativeMarket.com</a> &nbsp;</span></li> </ul> <h3>Jean-Thierry Roy: the MCG team QA</h3> <p>A relative recent addition to the 3ds Max team this year was our QA specialist Jean-Thierry Roy. JT is very active on the Autodesk Forums and the MCG Facebook page responding to questions, and tracking defects.&nbsp;<span style="line-height: 1.5em;">JT has also embarked on a number of interesting adventures with MCG that he has been <a href="https://www.youtube.com/user/Yrreihtnaej/featured"><strong>documenting on YouTube</strong></a> and posting on the <strong><a href="https://www.facebook.com/groups/1611269852441897/files/">MCG Facebook group (in the files section)</a></strong>.&nbsp;</span><span style="line-height: 1.5em;">One tool JT created that really stood out for me was a general Physics simulation tool called </span><a href="http://www.youtube.com/watch?v=c3s1lUDd_zA" style="line-height: 1.5em;"><strong>Bullet World</strong></a><span style="line-height: 1.5em;">. This tool enables you to select multiple objects in a scene that will interact together in a physics simulation. &nbsp;&nbsp;</span></p> <p>https://www.youtube.com/watch?v=piwBenIpptg</p> <h3>Martin Ashton: aka MCG Martin&nbsp;</h3> <p>Martin Ashton (who goes by &ldquo;MCG Martin&rdquo; on Facebook) is the man behind the <a href="/blogs/mcgblog"><strong>Max Creation Graph Blog</strong></a> this year. If you haven't seen his blog yet, you should. Martin has a real flair for creating top notch tutorials in a form that are clear, accurate, helpful, inspiring, and fun!&nbsp;</p>Mon, 18 Apr 2016 16:03:58 UTChttp://area.autodesk.com/blogs/chris/max-creation-graph-the-year-in-reviewEmulating a Particle System using MCGChristopher Diggins<p><span style="line-height: 1.5em;">In the M&amp;E division at Autodesk we have periodical hackathons where entire groups are given the opportunity to work on projects of our chosing for two-three days. We are then given the opportunity to showcase our work to the entire division and receive feedback from our leadership. I love this, because I get to work together with some really smart people on some interesting ideas.&nbsp;</span></p> <p>On<span style="line-height: 1.5em;">e of my hackathon projects last year, which I worked on with Kelvin Zelt, was to develop a simple particle system with MCG. Kelvin dubbed it project "Sprinkles". We managed to get a demo to work quite decently by using MCG as-is without any changes. We also found ways to make the core MCG evaluation much faster via lazy evaluation of arrays, but I'll save that for another post.&nbsp;</span></p> <p><span style="line-height: 1.5em;">In the Montreal Autodesk office at 10 Rue Duke, we have been hiring a lot of interns. This program is a huge success, and <strong><a href="http://careers.autodesk.com/careers/intern-and-new-grad-jobs">I encourage students to check out the listings</a></strong>. In fact several recent hires have come from the intern program. &nbsp;On the MCG team over the last year I have gotten to work with Kevin Derler, Marc-Antoine Nadeau, and Remi Cosette-Roberge. It has been a great experience for me, and they seem to have enjoyed it as well!&nbsp;</span></p> <p><span style="line-height: 1.5em;">Recently Remi took the particle project to another level: encapsulating a lot of the behavior in compounds and multi-threading the graph evaluation. &nbsp;</span></p> <p><span style="line-height: 1.5em;">https://www.youtube.com/watch?v=-NNu6amC3i4</span></p> <p><span style="line-height: 1.5em;">Because this was done using 3ds Max 2016,&nbsp;</span><span style="line-height: 1.5em;">I thought I would share it with you is as both an inspirational use of MCG, and a tutorial for some advanced concepts such as:</span></p> <ul> <li><span style="line-height: 1.5em;">Parallel pseudo-random number generation - see "RandInt" and "RandFloat"</span></li> <li><span style="line-height: 1.5em;">Using Ray Trace scene to quickly compute collision&nbsp;</span></li> <li><span style="line-height: 1.5em;">Caching to manage ray trace sceen&nbsp;</span></li> <li><span style="line-height: 1.5em;">Using simulation graphs to have predicatable results</span><span style="line-height: 1.5em;">&nbsp;</span></li> <li><span style="line-height: 1.5em;">Encapsulating complex behavior in compounds and using functions to describe behavior (e.g. particle construction, destruction, and updating).&nbsp;</span></li> </ul> <p><span style="line-height: 1.5em;">This MCG tool is not a real particle system, it is just a geometry objec that it generates a TriMesh that consists camera facing squares with UV coordinates, and vertex colors. Neither Remi or I are particularly good users of 3ds Max (though Remi has more skills than me already) so hopefully someone can share a better example!&nbsp;</span></p> <p><span style="line-height: 1.5em;">Here is the <strong><a href="/userdata/blogs/chris/MCGParticles.zip" mce_href="/userdata/blogs/chris/MCGParticles.zip">tool and a couple of sample 3ds Max files.</a></strong> You will need 3ds Max 2016, with at least SP1 installed. I hope you find it fun and useful! &nbsp;&nbsp;</span></p>Sat, 06 Feb 2016 13:21:39 UTChttp://area.autodesk.com/blogs/chris/emulating-a-particle-system-using-mcgMCG: Visual Functional ProgrammingChristopher Diggins<h2>Introduction</h2> <p><span style="line-height: 1.5em;">For those of you new to this blog, my name is Christopher Diggins, and I am a principal developer on 3ds Max. I work at Autodesk out of Montreal, Canada, and I have been fascinated with programming language implementation and design for 20 years.&nbsp;</span></p> <p><span style="line-height: 1.5em;">The last couple of years have been a real high point in my career, because I was being paid to design and implement a commerical programming language! The result was a functional visual programming language built into Autodesk 3ds Max 2016 called "Max Creation Graph" or MCG for short. &nbsp;<br /></span></p> <p><span style="line-height: 1.5em;">In case you are unfamiliar with 3ds Max, it is a comprehensive 3D modeling, animation, and rendering, solution for games, film, and motion graphics artists. It is also free for students and educators: &nbsp;</span><a href="http://www.autodesk.com/education/free-software/3ds-ma" style="line-height: 1.5em;">http://www.autodesk.com/education/free-software/3ds-ma</a><span style="line-height: 1.5em;">x. &nbsp;</span></p> <div><span style="line-height: 1.5em;"><br /></span></div> <h2><span style="line-height: 1.5em;">About MCG</span></h2> <p><span style="line-height: 1.5em;">MCG was initially developed as a way for people to create add-ins for 3ds Max that could create and manipulate geometry. Since geometry is mostly arrays of data (indices, vertices, faces, colors, UVs, selection sets) we decided to make a language that could efficiently manipulate large arrays of data. Because we wanted the language to perform efficiently and predictably in a multi-threaded environment it made sense to take ideas from the functional programming community, and to make a statically typed pure functional language. To be fair, while&nbsp;</span><span style="line-height: 1.5em;">the core language is pure functional, there are currently a number of stateful objects (e.g. Caches, random rumber generators) and large number of operations with side effects. Interestingly, we have found the pure functional approach to be very rewarding and will continue to work towards making it more pure in the future.&nbsp;</span></p> <h4><span style="line-height: 1.5em;">Language Influences</span></h4> <div><span style="line-height: 1.5em;">MCG is influenced by many programming languages, the most prominent of which are C#, Haskell, APL, and Softimage ICE. The MCG compiler emits .NET byte-code and uses MAXScript to interface with the 3ds Max plug-in system. No single aspect of the MCG language can be classified as novel, most of the ideas exist in other languages, but I haven't seen another visual programming language that has the same degree of support for functional programming.&nbsp;</span></div> <div><span style="line-height: 1.5em;"><br /></span></div> <h4>Statically Typed</h4> <p>MCG is statically typed. This means that the certain ill-formed programs and computations are detected at compile-time. For example in MCG you cannot add an integer (Int32) to a floating point value (Single), so the type system will detect this at compile-time and reject the program. In addition to the increased assurances that your program is correct, a static type system also enables the compiler to emit more efficient code than when types are checked dynamically at run-time. &nbsp;</p> <h4>Functional Programming</h4> <p>In a functional programming language such as MCG functions are first class citizens. They can be dynamically created, passed as function arguments, or returned from functions like any other data type. They can even be stored in arrays. <span style="line-height: 1.5em;">In my opinion, an excellent explantion of </span><a href="https://wiki.haskell.org/Functional_programming" style="line-height: 1.5em;">functional programming can be found here on the Haskell Wiki</a><span style="line-height: 1.5em;">.&nbsp;</span></p> <h4><span style="line-height: 1.5em;">Graphs as Computation&nbsp;</span></h4> <p>Computations in MCG are represented visually as directed acyclic graphs. Connections are implicitly directed from left-to-right. Each node in the graph represents a function (called an operator) that is applied to its input values. Each graph rooted at a particular node is an expression that represents the application of the function to its inputs.&nbsp;<span style="line-height: 1.5em;">If the &ldquo;function&rdquo; output of a node is used then the value output is an anonymous function (lambda abstraction) representing the graph&rsquo;s computation.&nbsp;</span></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCG_pics/Pic1.png" width="772" height="302" /></span></p> <p><span style="line-height: 1.5em;">When capturing a graph&rsquo;s computation as a function the function arguments are the set of unconnected inputs in the graph. </span></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCG_pics/Pic2.png" width="552" height="255" /></span></p> <p><span style="line-height: 1.5em;">The order of the arguments are determined by the order in which they appear when searching the graph right to left and top to bottom. The following example is from &ldquo;OffsetMeshes&rdquo; which offset each mesh in an array by a vector multiplied by its index in the aray.</span></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/MCG_pics/Pic3.png" width="870" height="288" /></span></p> <p>For a more detailed tutorial on how function connectors work in MCG, check out Martin Ashton&rsquo;s excellent <a href="/blogs/mcgblog/the-function-connector-part-1--reading-mcg-functions">two-part function tutorial on the MCG blog</a>.</p> <h3>Creating New Operators with Compounds</h3> <p>New operators in MCG can be created from graphs called &ldquo;compounds&rdquo;. A compound graph is saved with the extension &ldquo;.maxcompound&rdquo;. Compounds graphs must use an &ldquo;Output: compound&rdquo; operator as the terminal node of the graph, and use &ldquo;Input&rdquo; nodes (as opposed to &ldquo;Parameter&rdquo; nodes used by tools) to represent the graph&rsquo;s inputs.</p> <p>When a new compound is created and saved, it will be made available to the user (assuming it validates correctly) when the &ldquo;Reload Operators&rdquo; menu option is chosen. The next time 3ds Max starts up its signature will also appear in the help file.&nbsp;</p> <p>Because MCG has a type-inference engine you don&rsquo;t have to explicitly specify the output type of compounds, and can even specify &ldquo;Any&rdquo; for input parameters. The MCG compiler will attempt to assign the most precise type signature that can be determined will be assigned to the new operator. You can use &ldquo;Pass-through&rdquo; operators to help the type engine determine more precise types if needed.&nbsp;</p> <p>A compound is akin to defining functions in a text-based programming language. Like any programming language MCG is most effective when you break complex algorithms up into small well-defined reusable functions. &nbsp;</p> <h3>MCG Type System</h3> <p>The MCG type system is a subset of the C# type-system. Like C# the type system of MCG supports generic types and typed functions. The core primitive types of the MCG type system are:</p> <ul> <li><span style="line-height: 1.5em;">array type (IArray&lt;T&gt;)</span></li> <li><span style="line-height: 1.5em;">function types (Func&lt;T&gt;, Func&lt;T0, T1&gt;, etc.)</span></li> <li><span style="line-height: 1.5em;">tuple types (Tuple&lt;T0, T1&gt; and Tuple&lt;T0, T1, T2&gt;)</span></li> <li><span style="line-height: 1.5em;">integer numbers (Int32)</span></li> <li><span style="line-height: 1.5em;">floating point values (Single)</span></li> <li><span style="line-height: 1.5em;">and Boolean values (Boolean).</span></li> </ul> <p>There are a number of additional types that have been added to help with geometric processing (such as TriMesh and Vector3) and for interfacing with 3ds Max (e.g INode).&nbsp;</p> <p>What is displayed in the UI of the operators is actually an approximation of the type (e.g. IArray) but if you read the operator help or hover your mouse over a socket, you can see a more precise representation of the type. The approximation of the type is provided to do a preliminary type checking in the UI. For example the UI won&rsquo;t let you connect an Int32 to an IArray, but it will let you connect an IArray&lt;IArray&lt;Vector3&gt;&gt; where only an IArray&lt;Single&gt; is allowed. The final type-checking is done during the graph validation stage (which is also performed during evaluation and saving).&nbsp;</p> <p><img src="/userdata/blogs/chris/MCG_pics/Pic4.png" width="495" height="416" /></p> <h3>Immutable Data and Purity</h3> <p>A key feature of MCG is that it encourages a &ldquo;pure functional&rdquo; approach to constructing programs that avoids the usage of side-effects or mutable state.&nbsp;<span style="line-height: 1.5em;">Most data structures in MCG (e.g. arrays, meshes, tuples, vectors) are immutable data structures, meaning that they cannot be changed, you can only construct new versions of these structures. One result of this is that repeated calls to an operator like &ldquo;SetValue&rdquo; may create an entire copy of an array and can be inefficient. That said the MCG compiler employs strategies such as lazy evaluation to mitigate the performance issue.</span></p> <p>Immutable data structures offer several advantages :</p> <ol> <li><span style="line-height: 1.5em;">It is easier to reason about the result of a computation: order of evaluation in inconsequential&nbsp;</span></li> <li><span style="line-height: 1.5em;">Once a valid data structure has been constructed it cannot &ldquo;go wrong&rdquo;. This eliminates a very significant category of software defects.&nbsp;</span></li> <li><span style="line-height: 1.5em;">Multi-threading becomes most efficient: locks are no longer needed to synchronize access to data elements. Because values never change, there is no possibility of race conditions</span></li> <li><span style="line-height: 1.5em;">The compiler can perform employ advanced optimization techniques</span></li> </ol> <h3>Lazy Evaluation and Referential Transparency</h3> <p>The MCG compiler may choose a different internal representation of an immutable data structure if a computation always returns the same results given the same inputs and is side effect free. This property is called referential transparency.&nbsp;</p> <p>An example of an optimization performed by MCG is the &ldquo;Range&rdquo; operator which creates an immutable array of N integers from 0 to N-1. It is implemented &ldquo;lazily&rdquo; in that it generates values as requested rather than allocating a large block of memory filled with integers.&nbsp;</p> <p>This is similar to how LINQ (Language Integrated Natural Query) expressions work in C# and the lazy evaluation strategy of Haskell.</p> <h3>Side Effects</h3> <p>Functions with side effects create observable changes in the computation environment. For example they might change the state of a data structure, update the file system, or print something to a console. Examples of operators with side effects in MCG are &ldquo;Print&rdquo;, &ldquo;PseudoRandomFloat&rdquo;, and &ldquo;CreateEditableMesh&rdquo;. In computations with side effects the order of evaluation matter.&nbsp;</p> <p>Wherever possible you should avoid using functions with side effects, especially in higher-order array operations like &ldquo;Map&rdquo;, &ldquo;Filter&rdquo;, and &ldquo;Combine&rdquo; where there compiler may choose to evaluate the argument in different orders.&nbsp;</p> <h3>Higher Order Functions: Map, Filter, Combine, and Aggregate&nbsp;</h3> <p>Using MCG effectively requires the usage of a special class of higher-order array processing functions.&nbsp;<span style="line-height: 1.5em;">Any function that takes another function as an argument or returns a function as a result, is called a &ldquo;higher-order function&rdquo; or HOF for short. Higher order functions are very useful for working with sequences or arrays of data, as they enable you to describe succinctly data transformations without having to use loops or variables. &nbsp;</span></p> <p>In MCG arguably the most important array operations are &ldquo;Map&rdquo;, &ldquo;Filter&rdquo;, "Combine" and &ldquo;Aggregate&rdquo;. These are similar to the LINQ operations in C# &ldquo;Select&rdquo;, &ldquo;Where&rdquo;, "Zip" and &ldquo;Aggregate&rdquo;. In some programming languages the "Aggregate" function is called "fold" or "reduce".&nbsp;</p> <h4>Map&nbsp;</h4> <p>The map operation transforms an array into a new array by applying a function to all elements in a source array.&nbsp;</p> <p>&nbsp;<img src="/userdata/blogs/chris/MCG_pics/Pic5.png" width="600" height="296" /></p> <h4>Filter</h4> <p>The filter operation applies a predicate function (a function with one argument that returns a boolean) to an array and returns a new array that contains only elements for which the predicate is true.&nbsp;</p> <p><img src="/userdata/blogs/chris/MCG_pics/Pic6.png" width="740" height="297" /></p> <h4>Aggregate</h4> <p>An aggregate operation applies a binary function to each element in an array with an accumulator value, updating the accumulator value as it goes. The following example computes the sum of an array of values (whether they are Int32, Single, or Vector3).&nbsp;</p> <p>&nbsp;<img src="/userdata/blogs/chris/MCG_pics/Pic7.png" width="635" height="293" /></p> <h4>Combine</h4> <p>The combine operator applies a binary function to pairwise elements in two separate arrays to create a new array. The following example computes a dot product of two arrays.&nbsp;</p> <p>&nbsp;<img src="/userdata/blogs/chris/MCG_pics/Pic8.png" width="770" height="383" /></p> <h4>MapWithIndexes and Beyond</h4> <p>With the initial building blocks of &ldquo;Map&rdquo;, &ldquo;Filter&rdquo;, &ldquo;Aggregate&rdquo;, and &ldquo;Combine&rdquo;, it is possible to create new operators that are more specialized such as &ldquo;MapWithIndexes&rdquo; that acts as a &ldquo;Map&rdquo; but takes a binary function which takes the current index as the second input.&nbsp;</p> <p>&nbsp;<img src="/userdata/blogs/chris/MCG_pics/Pic9.png" width="749" height="323" /></p> <h4>SelectByIndex</h4> <p>Another compound (built using "Map") that is very useful in array processing and that deserves special mention is "SelectByIndex". The "SelectByIndex: operator takes an array of indices and an array of valeus, and returns a new array that contains the values as specified by the indices. Using this you can for example retrieve the vertices of a mesh arranged by face.&nbsp;</p> <p>&nbsp;&nbsp;<img src="/userdata/blogs/chris/MCG_pics/Pic10.png" width="1003" height="370" /></p> <h3>Multithreaded Operators: ParallelMap and ParallelCombine</h3> <p>Currentlly there are two operators in MCG that compute results in parallel: ParallelMap and ParallelCombine. These are functionally equivalent to Map and Combine, but are multi-threaded. You should only use them when you have identified a performance bottleneck. It is very important that the function arguments do not call any of the 3ds Max operations, since 3ds Max is not thread-safe. Note that overusing these operators can actually slow down your code. &nbsp;</p> <h3>Debugging MCG Graphs in Visual Studio</h3> <p>MCG tools emit a text output in the same folder as tool (e.g. mytool.txt) that can be loaded in the Visual Studio debugger. If you attach the Visual Studio debugger instance to 3ds Max you can set breakpoints in the text file and inspect the various values.&nbsp;</p> <p><img src="/userdata/blogs/chris/MCG_pics/AIco.png" width="1203" height="699" /></p> <p>This text format can be useful for understanding how MCG graphs are converted to byte-code. You&rsquo;ll notice that variables are declared and the results of the expression are assigned to variables. This allows graphs to be reused in multiple computations and to only be computed once.&nbsp;</p> <h3>Control Flow Operations</h3> <p>MCG is designed primarily for the processing of arrays of data. Many computations in MCG are more easily and efficiently solved when they can be expressed in terms of array operations. There are only a handful of basic control flow operations in MCG, but more can be defined using a bit of ingenuity and functional programming.&nbsp;</p> <p>The most basic control flow operator is the &ldquo;If&rdquo; operator which performs conditional evaluation of one of two inputs depending on whether the condition input is true or false.&nbsp;</p> <p>The &ldquo;While&rdquo; operator is a looping operator takes an initial value and two functions a loop body and a termination function. While the termination function returns false for the current value, the body function is called given the current value as an input. The result of the body function is given to the next iteration of the loop.&nbsp;</p> <p>The &ldquo;Repeat&rdquo; operator is similar to the while function but instead calls the body function a predetermined number of times, and also passes in the current loop index.<span style="line-height: 1.5em;">&nbsp;</span></p> <p>As an example of how to build more control flow operators, this example a &ldquo;RepeatWithoutIndices&rdquo; compound is defined using the &ldquo;Repeat&rdquo; operator.&nbsp;</p> <p>&nbsp;<img src="/userdata/blogs/chris/MCG_pics/Pic11.png" width="830" height="376" /></p> <h3><span style="color: #707070; font-family: 'Lucida Grande', Lucida, Verdana, sans-serif; font-size: 14px; font-weight: normal; line-height: 21px;">Notice the usage of the operator &ldquo;IgnoreSecond&rdquo; which returns the first input, and does nothing with this argument. This operator is noteworthy (along with ignore first) in that it can also be used to help force the arrangement of inputs and function arguments.&nbsp;</span></h3> <h3>Partial Application (Binding)</h3> <p>A slightly more esoteric higher order function that can be useful in some contexts are the various &ldquo;Bind&rdquo; operations (e.g. Bind1Of2) which create functions by binding (fixing) arguments of the function to a particular value. This process is called &ldquo;Partial Application&rdquo;. The result is a new function that requires fewer functions than the original.&nbsp;</p> <p>This advanced example demonstrates a generalized cartesian product function (f(xs[0], ys[0]), f(xs[0], ys[1]) &hellip; f(xs[n], ys[n]). The &ldquo;FlatMap&rdquo; operator applies a function (T -&gt; IArray&lt;U&gt;) to each element of an array (IArray&lt;T&gt;) but instead of returning IArray&lt;IArray&lt;U&gt;&gt; flattens the entire result into an IArray&lt;U&gt;.&nbsp;</p> <p>&nbsp;<img src="/userdata/blogs/chris/MCG_pics/Pic12.png" width="990" height="418" /></p> <p>One area where Bind has become quite useful is dealing with stateful objects like the random number generator. I'll refer you here to another <a href="/blogs/mcgblog/the-low-poly-modifier---part-2">excellent Blog post by Martin Ashton</a> for more detail on this usage of Bind in this context.&nbsp;</p> <h3>Final Words</h3> <p>Thanks for following me down this long rabbit hole. I hope this article whetted your appetite for functional visual programming and that you consider give MCG a try!</p> <p>PS: I'm especially interested in hearing from computer science educators interested in using MCG to teach functional or visual programming to their students.&nbsp;</p>Fri, 30 Oct 2015 23:07:37 UTChttp://area.autodesk.com/blogs/chris/mcg-visual-functional-programmingFlux and the Max Creation Graph Sample Pack 2Christopher Diggins<p class="MsoNormal">To celebrate the fact that we now have over 3000 members on the <a href="https://www.facebook.com/groups/1611269852441897/"><strong>MCG Facebook page</strong></a>, and to make up for the long periods without posts I wanted to share a new set of MCG tools and compounds: y<span style="line-height: 1.5em;">ou can download the </span><strong><a href="/userdata/blogs/chris/MCGSamplePack2.zip" style="line-height: 1.5em;">MCG Sample Pack 2 here</a></strong><span style="line-height: 1.5em;">.</span></p> <p class="MsoNormal">Before installing the Sample Pack I recommend you first back-up your entire MCG user folder (%userprofile%/Autodesk/3ds Max 2016/Max Creation Graph). You can then un-zip the file contents directly into your MCG user folder. This package includes all of the tools and compounds from the <strong><a href="/blogs/chris/max-creation-graph-mcg-sample-pack-for-3ds-max-2016">original sample pack</a></strong>&nbsp;and includes <strong><a href="/blogs/chris/curvature-to-vertex-color-modifier-using-max-creation-graph">updates to the MCG curvature sample</a></strong>, so overwriting existing files should be fine, unless of course you made your own modifications to these tools or compounds, which is why <em>I strongly recommend backing up your folder</em>!</p> <p class="MsoNormal">At the core of this sample pack is a set of modifiers called the Flux toolkit for performing object cloning, placement, and creating animations. These mini-tools work together to enable users to create sophisticated effects as demonstrated in this video:<o:p></o:p></p> <p class="MsoNormal">http://www.youtube.com/watch?v=CDkP1cjOLBU</p> <p class="MsoNormal">Even if you don't find the Flux toolkit directly useful it does demonstrate a very powerful workflow for MCG tools: using Map Channels to share data between tools. It also serves to showcase and test a large number of new compounds the address common challenges that arise when writing MCG tools. For example orienting objects towards another, generating random points on a surface, interpolating positions and tangents along a spline, and so forth.&nbsp;</p> <h3 class="MsoNormal"><span style="line-height: 1.5em;">How Flux Works</span></h3> <p class="MsoNormal"><span style="line-height: 1.5em;">Flux works by storing transform matrices in a map channel to represent the position, rotation, and scale of each cloned object. You place a Flux initializer modifier (e.g. Flux_Initialize_Vertices) on an object to initialize the map channel. Next you place the Flux modifiers you want. Finally you add a Flux_Evaluate modifier on top to generate clone a mesh at each of the matrices.</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">Things get very interesting when you use the Flux blend modifiers (e.g. Flux_Blend_Falloff) to interpolate between the top and previous Flux effect. This is where the &ldquo;combine effect&rdquo; check-box can be useful. Most Flux effects also have a "strength" value that allows you to control an interpolation between the Flux effect (or combined effect) and the previous effect. Flux effects can also be copied to and from other map channels to enable your to reuse intermediate effects (e.g. using Flux_Store_Data and Flux_Load_Data).&nbsp;</span></p> <h2 class="MsoNormal"><span style="line-height: 1.5em;">Flux Modifiers</span></h2> <p class="MsoNormal">The following is a list of the Flux modifiers <o:p></o:p></p> <table class="MsoTableGrid" border="1" cellspacing="0" cellpadding="0" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt;"> <tbody> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><b>Flux Modifier<o:p></o:p></b></p> </td> <td width="108" valign="top" style="width: 81.0pt; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><b>Modifier Type<o:p></o:p></b></p> </td> <td width="391" valign="top" style="width: 293.4pt; border: solid windowtext 1.0pt; border-left: none; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><b>Description<o:p></o:p></b></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Align Axis<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Orients one axis of each matrix<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Blend Falloff<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Blend<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">The effect is applied to matrices in a specified part of the array, with a falloff<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Blend Offset<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Blend<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">The effect strength is applied to matrices with before the specific location in the array.<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Blend Randomly<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Blend<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">The effect is applied with random strength to different matrices<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Blend Region<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Blend<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">The effect is stronger near the specified node<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Blend Sine Wave<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Blend<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">The effect strength is controlled by a sine wave. <o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Circle<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Arranges the transforms in a circle<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Concatenate<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creation<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Adds two arrays of matrices together<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Evaluate<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Evaluate<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creates clones of geometry transformed according to each matrix in the map channel<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Filter by Angle<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Filter<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Removes matrices that are rotated more or less than a specific angle<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Filter by Box<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Filter<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Removes (or keeps) matrices that are within a specific distance from the bounding box. <o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Filter Overlapping<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Filter<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Removes matrices that are at the same position<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Filter Range<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Filter<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Removes a number of matrices starting from the specified matric<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Initialize Faces<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Initialization<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creates an array of matrices at each face of the base object<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Initialize Vertices<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Initialization<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creates an array of matrices at each vertex of the base object<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Initialize<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Initialization<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Create an array of identity matrices<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Lerp Nodes<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Positions matrices between the matrices of two nodes using linear interpolation (Lerp)<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Lerp Spacing<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Other<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creates new matrices between each pre-existing matrix that has the specified spacing<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Line Corners<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creation<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Each matrix is duplicated. Every pair of matrices is oriented away from the line segment it creates. <o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Load Data<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Data<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Copies the matrices from another map channel<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Mesh Loft<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Meshing<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creates a mesh by lofting a shape along the path defined by the matrices.<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Mesh Strip<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Meshing<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creates a mesh strip assuming the first and second half of the matrix positions forms the bottom and top of the mesh strip respectively.<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Move<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Moves the matrices towards a target node.<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Orient Axis<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Orients an axis towards the specified node.<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Orient<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Orients each matric towards a target using a primary and secondary axis of orientation.<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Orient to Next <o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Orients each matrix towards the next one. <o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Path<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Initialization<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creates matrices evenly spaced along a spline.<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Redistribute<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creation<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Treats the matrices as a path, and redistributes N matrices evenly or randomly between the other matrices.<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Replicate <o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creation<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Creates N copies of the matrices, each offset by some amount<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Reset<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Resets all matrices to the identity matrix<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Rotate<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Rotates all matrices<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Scale to Target<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Scales all matrices according to the distance from a node<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Scale<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Scales all matrices <o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Scatter<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Places matrices randomly on the surface<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Store Data<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Data<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Copies the matrices to another map channel<o:p></o:p></span></p> </td> </tr> <tr> <td width="139" valign="top" style="width: 1.45in; border: solid windowtext 1.0pt; border-top: none; mso-border-top-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Flux Translate<o:p></o:p></span></p> </td> <td width="108" valign="top" style="width: 81.0pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Transform<o:p></o:p></span></p> </td> <td width="391" valign="top" style="width: 293.4pt; border-top: none; border-left: none; border-bottom: solid windowtext 1.0pt; border-right: solid windowtext 1.0pt; mso-border-top-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt 0in 5.4pt;"> <p class="MsoNormal"><span style="font-size: 10.0pt; mso-bidi-font-size: 11.0pt;">Moves the matrices</span></p> </td> </tr> </tbody> </table> <p class="MsoNormal"><span style="line-height: 1.5em;"><br /></span></p> <h3 class="MsoNormal">Extending Flux Yourself</h3> <p class="MsoNormal"><span style="line-height: 1.5em;">While Flux is very flexible and powerful you may find that non-trivial compound effects require a lot of clicking to switch back and forth between modifiers, not to mention your scene will slow down substantially when there are too many modifiers on your stack. This is where you can look into using MCG to create your own Flux tools that combine effects. The graphs for these tools are designed to be small and easy to understand so that you can reuse and extend them.</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/Flux-Translate.jpg" /></span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">Some of the samples even show how Flux can be extended to do unexpected things like creating meshes.</span></p> <h3>Final Words&nbsp;</h3> <p>A big thank you to the amazing team working on Max Creation Graph and to the support of our user community!&nbsp;</p>Mon, 19 Oct 2015 14:56:26 UTChttp://area.autodesk.com/blogs/chris/flux-and-the-max-creation-graph-sample-pack-2Using Bullet Physics in Max Creation GraphChristopher Diggins<p class="MsoNormal"><span style="line-height: 1.5em;">As promised in my <a href="/blogs/chris/max-creation-graph-updates-in-3ds-max-2016-extension-1"><strong>previous blog post</strong></a> about MCG features in extension 1&nbsp;</span><a href="/userdata/blogs/chris/BulletSamples.zip" style="line-height: 1.5em;"><strong>here are two tools</strong></a><span style="line-height: 1.5em;"> created for 3ds Max 2016 Extension 1 that utilize the new Bullet Physics operators. The first tool is an MCG transform controller written by our QA Jean-Thierry Roy that applies basic physics to an object and allows you to pick multiple obstacles. The second tool is an MCG modifier I wrote that clones an object and applies simple physics to all of the cloned objects. Both tools use the new node array parameter.</span></p> <p class="MsoNormal">https://www.youtube.com/watch?v=tNBOFtl49Gg</p> <p class="MsoNormal"><span style="line-height: 1.5em;">JT&rsquo;s animation controller is an example of a new type of MCG tool called a &ldquo;simulation&rdquo; graph. A simulation graph is evaluated at regular incremental time intervals regardless of how the user moves the time slider. If the user moves the time slider back in time, the simulation is restarted from the beginning of the graph. This is useful when scene objects can affect the simulation for example if some of the rigid bodies are kinematic. In this case you need the simulation to evaluate at regular intervals.</span></p> <p class="MsoNormal">In the cloned physics demo I simplified things by not making it a simulation graph. I also connect the &ldquo;time&rdquo; parameter of the simulation to a slider so that it can be key-framed independently.&nbsp;<span style="line-height: 1.5em;">In the process I wrote some compounds to help simplify the set-up of rigid body simulations when no kinematic bodies are involved.&nbsp;</span></p> <p class="MsoNormal">If you haven't seen it you also to have to check out this great video made by Chris Murray showing off the MCG Animation Controllers feature.&nbsp;</p> <p class="MsoNormal"><span style="line-height: 1.5em;">https://vimeo.com/135870585</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">I hope you find these examples useful. Check out the </span><strong style="line-height: 1.5em;"><a href="https://www.facebook.com/groups/1611269852441897/">MCG Facebook group</a></strong><span style="line-height: 1.5em;">&nbsp;and the </span><a href="http://www.scriptspot.com/3ds-max/mcg" style="line-height: 1.5em;"><strong>MCG hub at ScriptSpot</strong></a><span style="line-height: 1.5em;"> for other samples from the user community!&nbsp;</span></p> <p class="MsoNormal"><br /><o:p></o:p></p>Tue, 18 Aug 2015 02:48:48 UTChttp://area.autodesk.com/blogs/chris/using-bullet-physics-in-max-creation-graph-in-3ds-max-2016Max Creation Graph Updates in 3ds Max 2016 Extension 1Christopher Diggins<p class="MsoNormal"><span style="line-height: 1.5em;">I am pleased to announce that we have added new functionality to MCG in <a href="/blogs/max/3ds-max-2016-extension-1"><strong>3ds Max 2016 Extension 1</strong></a>. You can now create animation controllers using Max Creation Graphs. We also have made it easier to create dynamic rigid body physics simulations with the integration of Physics bullet library.</span><span style="line-height: 1.5em;">&nbsp;Smaller improvements&nbsp;</span><span style="line-height: 1.5em;">include added support for Vector3 parameter types and arrays of 3ds Max objects (INode) or floating point values (Single).&nbsp;</span></p> <p class="MsoNormal">In addition to other fixes, one notable bug fix provided with SP1 (to all 3ds Max 2016 users) that enables users to get mapping channels (e.g. Vertex Color Channels, etc.). This means it is now possible to store and access data in map channels.</p> <p class="MsoNormal">Here are some of the highlights of the work on MCG this extension.&nbsp;</p> <h2 class="MsoNormal">MCG Animation controllers&nbsp;</h2> <p class="MsoNormal">The extension ships with several new controllers created using MCG:&nbsp;</p> <ul> <li><span style="line-height: 1.5em;">Lookat with Billboard Constraint</span></li> <li><span style="line-height: 1.5em;">RaytoSurface Position/Orientation/Transform Constraint</span></li> <li><span style="line-height: 1.5em;">Rotational Spring with one or three degrees of freedom</span></li> </ul> <div> <p class="MsoNormal">You can find the source graphs for these tools in <strong>C:\Program Files\Autodesk\3ds Max 2016\MaxCreationGraph\Tools.</strong> Warning though, they are not for those uninitiated in the ways of MCG.</p> <p class="MsoNormal">To get you started a little more gently into the world of controller creation, I&rsquo;ve included a <strong><a href="/userdata/blogs/chris/Orbit.zip" mce_href="/userdata/blogs/chris/Orbit.zip">sample MCG position controller here</a></strong> called &ldquo;Orbit&rdquo; that rotates an object around a target on the XY plane given the speed and radius.&nbsp;</p> <p class="MsoNormal"><img src="/userdata/blogs/chris/Oribit-Graph-Screengrab_001.jpg" width="750" height="440" style="line-height: 1.5em;" /></p> </div> <p class="MsoNormal"></p> <h2 class="MsoNormal">MAXScript Animation Controller Plugins<o:p></o:p></h2> <p class="MsoNormal">While working on MCG animation controller we also added the capability to create scripted animation controller plug-ins in MAXScript. This differs from the traditional &ldquo;script controller&rdquo; in that the new controller has a parameter block, a UI displayed in the motion panel, and is listed in the assign controller dialog.</p> <p class="MsoNormal">To demonstrate the new MAXScript scripted controller capabilities, I&rsquo;ve included a <strong><a href="/userdata/blogs/chris/TimeDilation.zip" mce_href="/userdata/blogs/chris/TimeDilation.zip">&ldquo;Time Dilation&rdquo; scripted MAXScript position controller plug-in</a></strong>. You use it by assigning it to an object&rsquo;s position track that already has a controller assigned. It will cause the object to behave as if time is slowed down and then sped up between the specified begin and end frames. This is done by applying a mathematical function (&ldquo;pow&rdquo; to be specific) to the current time and passing the transformed time to the previous controller to get the value.&nbsp;</p> <p class="MsoNormal">Note that one limitation of this tool is that you can only access the previous controller through MAXScript.</p> <h2 class="MsoNormal"><span style="line-height: 1.5em;">Dynamic Rigid Body Simulations with Bullet Physics</span></h2> <p class="MsoNormal"><span style="line-height: 1.5em;">We added new operators to MCG that simplify the creation of rigid body simulations using the Bullet physics library. To support this we also have a new property that tools can have called "Is Simulation" that appears in the tool's "properties" dialog. This controls how caches are handled and forces the tool to re-evaluate at each frame.</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">The new rigid body simulation operators are complex enough that I will be blogging about them in a later post.</span></p> <p class="MsoNormal">For now I leave you with a video from one of our developers Nathan Loofbourrow, where he talks about the work in MCG this release.</p> <p class="MsoNormal">https://vimeo.com/135685708</p>Tue, 11 Aug 2015 16:13:53 UTChttp://area.autodesk.com/blogs/chris/max-creation-graph-updates-in-3ds-max-2016-extension-1Max Creation Graph Geometry StackerChristopher Diggins<p class="MsoNormal"><span style="line-height: 1.5em;">A while ago Ishak Suryo L posted a very useful tool that allows you to stack different geometry on top of each other along the Z axis:</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">http://vimeo.com/126746868</span><span style="line-height: 1.5em;"></span></p> <div><span style="line-height: 1.5em;">You can find Ishak&rsquo;s original </span><a href="http://www.scriptspot.com/3ds-max/mcg/mcg-stackmesh" style="line-height: 1.5em;">MCG_Stacker tool on ScriptSpot</a><span style="line-height: 1.5em;">.</span></div> <p class="MsoNormal"><span style="line-height: 1.5em;">I&rsquo;ve developed my own variation of this tool (<a href="/userdata/blogs/chris/Stacker.zip">download it here</a>) that also works along the X or Y axis. In addition if you don&rsquo;t provide a &ldquo;target&rdquo; node to stack, it clones the base mesh along the given axis.</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">http://www.youtube.com/watch?v=KIj6MzRB2P4</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">To stay abreast of new and cool MCG tools like these be sure you join the <a href="https://www.facebook.com/groups/1611269852441897">MCG Facebook group</a></span><span style="line-height: 1.5em;">.</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">In other news if you are going to be at Siggraph come on by to the Autodesk Vision Series talk on Procedural Content Creation by Martin Coven and myself which will be on Tuesday, 11 August at 4:30 PM &nbsp;Los Angeles Convention Center, Room 408A.</span></p> <p class="MsoNormal"><span style="line-height: 1.5em;">I hope to see you there!&nbsp;</span></p>Thu, 06 Aug 2015 22:39:43 UTChttp://area.autodesk.com/blogs/chris/max-creation-graph-geometry-stackerCurvature to Vertex Color Modifier using Max Creation GraphChristopher Diggins<p>One popular request on the <strong><a href="/3dsMaxFeedback.autodesk.com">Autodesk 3ds Max Feedback site</a></strong>&nbsp;is the <strong><a href="http://3dsmaxfeedback.autodesk.com/forums/80695-general-feature-requests/suggestions/1495159-curvature-map#comments">curvature map</a></strong>.&nbsp;<span style="line-height: 1.5em;">While you can't create procedural texture maps with Max Creation Graphs (at least not now) you can create modifiers that set the vertex color map and then use the vertex color map to drive materials.</span></p> <div><span style="line-height: 1.5em;">https://www.youtube.com/watch?v=dEzwgBn7aqo.</span></div> <div><span style="line-height: 1.5em;"><br /></span></div> <p><span style="line-height: 1.5em;">In the zip file&nbsp;<strong><a href="/userdata/blogs/chris/CurvatureMCG.zip">CurvatureMCG.zip</a></strong>&nbsp;there are three tools and a few supporting compounds. To use the simply unzip the file into your MCG user folder&nbsp;(</span><span style="line-height: 1.5em;">%userprofile%/Autodesk/3ds Max 2016/Max Creation Graph) and restart 3ds Max. Alternatively you can go into the MCG editor and select "Operators &gt; Reload Operators" and then "Build &gt; Evaluate all Tools".</span></p> <p>In the package are three MCG modifiers:</p> <p><span style="line-height: 1.5em;">1.</span><span class="Apple-tab-span" style="white-space: pre;"> </span><strong>Curvature</strong> -&nbsp;<span style="line-height: 1.5em;">Computes curvature at each face-vertex based on the angle between the vertex normal and the face normal. The value is clamped at 90 degrees +/- a delta (default 10), converted to a gray scale value, and stored in the vertex color channel.</span></p> <p><span style="line-height: 1.5em;">2.</span><span class="Apple-tab-span" style="white-space: pre;"> </span><strong>SmoothVertexColors</strong> -&nbsp;<span style="line-height: 1.5em;">A modifier that smooths the vertex colors in two steps: </span><span style="line-height: 1.5em;">a.</span><span class="Apple-tab-span" style="white-space: pre;"> </span><span style="line-height: 1.5em;">Gives each face the same vertex color across the face.&nbsp;</span><span style="line-height: 1.5em;">b.</span><span class="Apple-tab-span" style="white-space: pre;"> </span><span style="line-height: 1.5em;">At each vertex averages the vertex color based on the vertex color of each contributing corner.&nbsp;</span></p> <p><span style="line-height: 1.5em;">3.</span><span class="Apple-tab-span" style="white-space: pre;"> </span><strong>VertexColorGrayScaleToColor</strong> -&nbsp;<span style="line-height: 1.5em;">A modifier for visualizing gray scale vertex colors. It converts gray-scale values in the vertex color channel to RGB where 0,0,0 is red, 0.5,0.5,0.5 is green, and 1.0,1.0,1.0 is blue.&nbsp;</span></p> <p><span style="line-height: 1.5em;">I'm also sharing with you a scene (<strong><a href="/userdata/blogs/chris/DragonWithCurvature.zip">DragonWithCurvature.zip</a></strong>) with the modifiers and a simple material applied to the Stanford dragon.</span></p> <h2>Under the hood</h2> <p><span style="line-height: 1.5em;">In order to understand what is going on in the MCG graphs, the key is to first understand how the TriMesh structure is organized as a set of immutable (unchanging) data-channels.&nbsp;</span><span style="line-height: 1.5em;">&nbsp;</span></p> <p><span style="line-height: 1.5em;"><img src="/userdata/blogs/chris/2015-04-19_2349.png" /></span></p> <p><span style="line-height: 1.5em;"><br /></span></p> <p>Data channels are arrays of data associated with different mesh elements: faces, vertices, face-vertices (i.e. the corners of each face), and edges. Data channels can have different types (Int32, Boolean, Single, Vector3, etc.) and can be either direct or indirect. A direct data channel mean the data buffer has the same length as the associated number of elements, and can be indexed in the same manner. An example of this are the material IDs data channel.&nbsp;<span style="line-height: 1.5em;">&nbsp;</span></p> <p>An indirect data channel has two arrays: the data buffer and an index buffer. The index buffer is the same length as the number of elements, and is used to lookup data elements. The most common example of this is the topology data channel. The topology data channel has a vertex buffer and an index buffer. The index buffer is the same length as the number of face-vertices (i.e. corners of faces). This is how most 3D APIs represent triangular meshes. &nbsp;We say that the topology channel is an indirect data channel of type "Vector3" that is associated with face-vertices.&nbsp;</p> <p>In 3ds Max a common category of data channel is called a MapChannel. In MCG the map channel is an indirect data channel of type Vector3 that is associated with face-vertices. Map channels are exposed to 3ds Max users via the <strong><a href="http://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/3DSMax/files/GUID-5945F5FC-0D14-48BF-B2C5-31CE6C4DCB05-htm.html">Channel Info Utility</a>&nbsp;</strong>which&nbsp;is one way to understand them better. &nbsp;</p> <h2><span style="line-height: 1.5em;">About Vertex Colors&nbsp;</span></h2> <p>Despite the somewhat misleading name v<span style="line-height: 1.5em;">ertex colors are a general purpose mechanism to store Vector3 data (triples of floating point values) with particular face-vertices. A face-vertex is a corner of a triangle. There are exactly N*3 face-vertices in a TrIMesh, where N is the number of face. This is usually different than the number of vertices, because multiple faces can share a vertex.</span></p> <p><span style="line-height: 1.5em;"><strong>BUG ALERT</strong>: due to a bug in the current version of MCG, the vertex data channel data buffer must have exactly N*3 data elements.&nbsp;</span></p> <p>For more information on Vertex Colors, and an arguably better explanation of mapping channels in general, I suggest reading the topic <strong><a href="http://help.autodesk.com/view/3DSMAX/2015/ENU/?guid=__files_GUID_CBBA20AD_F7D5_46BC_9F5E_5EDA109F9CF4_htm">Understanding Texture Coordinates and Vertex Colors</a></strong>&nbsp;in the MAXScript help.</p> <p>I hope you find the samples useful, and I'd love to hear what type of MCG tools you come up with that do magic with vertex colors!&nbsp;</p>Mon, 20 Apr 2015 03:29:39 UTChttp://area.autodesk.com/blogs/chris/curvature-to-vertex-color-modifier-using-max-creation-graphMax Creation Graph (MCG) Sample Pack for 3ds Max 2016Christopher Diggins<p>Now that 3ds Max 2016 is <strong><a href="http://www.autodesk.com/products/3ds-max/overview">available for download</a></strong>&nbsp;I'm pleased to announce a set of 30 sample MCG tools and 80 new compounds that you can download, use, and learn from!&nbsp;</p> <p><span style="line-height: 1.5em;">https://www.youtube.com/watch?v=ckfdHlzisTY</span></p> <div><span style="line-height: 1.5em;">In order to install the tools unzip the contents of </span><strong style="line-height: 1.5em;"><a href="/userdata/blogs/chris/MaxCreationGraph.zip" style="line-height: 1.5em;">MaxCreationGraph.zip</a></strong><span style="line-height: 1.5em;">&nbsp;</span><span style="line-height: 1.5em;"><span style="line-height: 1.5em;">and it into your Max Creation Group user folder. You can navigate directly to that folder by pasting</span></span> <pre>%userprofile%/Autodesk/3ds Max 2016/Max Creation Graph</pre> <span style="line-height: 1.5em;">into your Windows explorer.&nbsp;</span></div> <p>If you have any other compounds and tools installed, be sure to back them up first, in case some files in the zip package have the same name as existing files. When you restart 3ds Max you should see a number of new modifiers in the modifier pull-down. Each name of the new modifier starts with "A" (e.g. "APush"). There will also be a new category in the object creation panel called "Max Creation Graph" with several new tools.&nbsp;</p> <p>I have also created a sample test file that you can load once you unzip the tools and restart 3ds Max here:&nbsp;<strong><a href="/userdata/blogs/chris/MCGSampleTestScene.zip" style="line-height: 1.5em;">MCGSampleTestScene.zip</a></strong>.&nbsp;</p> <p><img src="/userdata/blogs/chris/MCGSampleScene.png" width="958" height="789" /></p> <p><span style="line-height: 1.5em;">Your comments and questions are certainly appreciated, enjoy!</span></p>Fri, 17 Apr 2015 03:59:49 UTChttp://area.autodesk.com/blogs/chris/max-creation-graph-mcg-sample-pack-for-3ds-max-2016Introducing Max Creation GraphsChristopher Diggins<h1>Introducing Max Creation Graphs (MCG)</h1> <p><img style="float: right;" src="/userdata/blogs/chris/basement.jpg" width="138" height="192" /><span style="line-height: 1.5em;">Now that <a href="/blogs/max/introducing-3ds-max-2016">3ds Max 2016 has been officially announced</a> I can finally come out of stealth mode and tell you why you haven't heard from me for over a year!</span></p> <p><a href="/blogs/max">Eddie Perlberg</a>&nbsp;had me locked me up in a basement along with Martin Coven and a team of talented developers and QA until we completed the&nbsp;<a href="http://3dsmaxfeedback.autodesk.com/forums/80695-general-feature-requests/suggestions/1467083-ice-for-3ds-max-modifiers">#1 most request feature for 3ds Max</a>.</p> <p><span style="line-height: 1.5em;">The result of our effort is a new feature in 3ds Max 2016 called the </span><strong style="line-height: 1.5em;">Max Creation Graph</strong><span style="line-height: 1.5em;"> editor (or MCG for short). This tool enables user to create modifiers, geometry, and utility plug-ins using a visual node-based workflow.</span></p> <p>With MCG you can create a new plug-in for 3ds Max in <b>minutes</b> by simply wiring together parameter nodes, computation nodes, and output nodes. The resulting graph can then be saved in an XML file (.maxtool) or be packaged with any compounds (.maxcompound) it depends in a ZIP file (.mcg) which you can share easily with 3ds Max users.</p> <p>https://www.youtube.com/watch?v=E2Pv2-zjHD4</p> <p>Once an MCG tool is evaluated you will have one of the following:</p> <ul> <li>New objects primitive in a the "Max Creation Graph" category in the creation panel</li> <li>A new modifier in the modifier pull-down</li> <li>A new MAXScript utility</li> <li>A new MAXScript function</li> </ul> <p><span style="line-height: 1.5em;">After evaluation two files are generated next to your .maxtool file</span></p> <ul> <li>A MAXScript plugin wrapper (.ms)</li> <li>A representation of the .NET function compiled from the graph (.txt)</li> </ul> <h2>MCG is not Softimage ICE</h2> <p>Despite the title of the original request on user feedback (which you might notice was first suggested by Martin Coven before we hired him, I'm sure he is glad to finally get his votes back) and the obvious similarities this is not an integration of Softimage ICE in 3ds Max. At the heart of MCG is a brand new visual programming language we developed on top of the .NET framework.</p> <p><img src="/userdata/blogs/chris/RingCloneGraph.png" width="1145" height="891" /></p> <p>Some of you may also be familiar with another open-source visual language from Autodesk called <a href="http://dynamobim.com/">Dynamo</a> and see some similarities. Dynamo is very similar to MCG (it is easy to extend using .NET and supports some functional programming concepts) but at the <a href="http://steellworks.blogspot.ca/2013/01/dynamo-fscheme-refactor-progress.html">core is an interpreter</a> whereas MCG is compiled directly to .NET byte-code. This design choice made sense for Dynamo, because it was designed for parametric geometry construction, however the performance was not sufficient to enable us to create tools for 3ds Max users.</p> <p>3ds Max users expect all parameters of geometry and modifiers to be able to be animated and to have the results updated in near real-time in the viewport (usually buildings don't dance, but they can in 3ds Max). Because of this requirement we had to develop a full compiler. I'll bore you with more details if you buy me a beer (or I accidentally start to blog while drinking).</p> <h2>A functional dataflow visual programming language</h2> <p>For the most part MCG is a traditional visual programming language. Nodes perform a transformation on data that flows through input connections and output the result to the output "value" connection.</p> <p>One characteristic of MCG that is immediately apparent is the fact that there are "function" connection outputs. This enables computations to flow through a graph as data. In computer science we call these <a href="http://en.wikipedia.org/wiki/First-class_function">first-class functions</a>.</p> <p style="padding-left: 30px;">When a node is connected from the "function" output, the entire left sub-graph is treated as a function, with unconnected inputs in the graph treated as function arguments. This is equivalent to the <a href="http://en.wikipedia.org/wiki/Lambda_calculus">lambda abstraction operation</a>. More on this in later tutorials.</p> <p>In MCG we can not only pass functions as arguments to higher-order functions like "Map" or "Combine" we can also return functions from operators such as "Bind" which performs a partial application or "Compose" which performs function composition. We can also store functions in arrays. I'll go into more details on this in a future blog post.&nbsp;</p> <p><img src="/userdata/blogs/chris/RingOfTeapots.png" style="line-height: 1.5em;" /></p> <p>A few things to note about MCG: most data that flows through the graph (with a few exceptions such as "INode", "Cache<t>", and "Random" objects) are immutable data structures. In other words MCG is nearly a pure functional programming language (like <a href="http://en.wikipedia.org/wiki/Haskell_(programming_language)">Haskell</a>). An example of this is that when you send data into a "SetValue" node the array you get on the other side is a new array, and the original one remains unchanged. This was done so that multi-threaded evaluation (e.g. via "ParallelMap") could be done quickly and easily. I promise more information on multithreading in a later post. </t></p> <h2>The Future</h2> <p>We are a publicly traded company which implies certain legal obligations, so unfortunately I can never talk about the future as much as I would like. It always makes me a bit sad, because I spend a lot of time thinking about the future &hellip; more time than my boss would like. :-)</p> <p>https://www.youtube.com/watch?v=tmudH_C97O4</p> <p>At the very least I hope that I have proven to you that by going on to <a href="/3dsMaxFeedback.autodesk.com">3dsMaxFeedback.autodesk.com</a> YOU are directly influencing the future. Yes, big requests might take four years to deliver on, and sometimes we can't tell you we are working on them (it is a very competitive business after all) but we are paying very close attention.</p> <p>I never forget that without the support of our users there would be no 3ds Max, and I wouldn't have my dream job.</p> <p><span style="color: #5d9013; font-family: ff-meta-web-pro, Arial, sans-serif; font-size: 24px; line-height: 1.2em;">Sample MCG Tools</span></p> <p>For some <a href="/blogs/chris/max-creation-graph-mcg-sample-pack-for-3ds-max-2016"><strong>sample MCG tools made by our team see this blog post</strong></a>.&nbsp;<span style="line-height: 1.5em;">There are also a number of 3rd party sample tools and videos posted on the </span><a href="https://www.facebook.com/groups/1611269852441897" style="line-height: 1.5em;"><strong>MCG Facebook page</strong></a><span style="line-height: 1.5em;">.</span></p> <p>On the Autodesk 3ds Max Learning Channel on YouTube you can find a tutorial series on Max Creation Graphs:&nbsp;</p> <p>https://www.youtube.com/watch?v=YBPVUvvMdD0&amp;list=PLnKw1txyYzRl1IVsbSFwd-c9i9cz-rRJ1</p> <p><span style="line-height: 1.5em;">For inspirstaion, here was the demo video made by Martin Coven:&nbsp;</span></p> <p><span style="line-height: 1.5em;">https://www.youtube.com/watch?v=3nsAlw_j4lQ</span></p> <div></div> <p><span style="color: #5d9013; font-family: ff-meta-web-pro, Arial, sans-serif; font-size: 24px; line-height: 1.2em;">Acknowledgements</span></p> <p>MCG would not have been possible without the hard work of a talented and passionate development team. The core team included Martin Coven as designer and instigator, myself as architect, along with Abdelhak Ouhlal, Attila Szabo, Clint Lewis, Rick Delesdernier, and Roman Woelker. Larry Minton and Tom Hudson also contributed at crucial points to help develop key functionality. Martin Ashton played an important role developing the initial prototype of MCG and I look forward to the tutorials he creates on his <a href="http://www.youtube.com/user/ScriptingSDKHowTos">YouTube SDK and scripting learning channel</a>.</p> <p>Of course this is an effort that spanned the entire 3ds Max team. No feature is developed in isolation, it takes an entire team of people working together to deliver 3ds Max. The whole team has worked hard to create a release that I am truly proud of.</p> <p>I personally want to thank Eddie Perlberg, Michael Russo, Kelcey Simpson, and Chris Young for believing that our team could deliver on such a bold and daring vision, and supporting us through the process.</p> <p>I also want to thank all of the Beta members and 3dsMaxFeedback contributors for their invaluable feedback, support, and encouragement.</p> <h2>Final Words</h2> <p><span style="line-height: 1.5em;">For now I want to leave you with the same words that Eddie shared with me recently "This is just the beginning."</span></p>Mon, 13 Apr 2015 01:07:37 UTChttp://area.autodesk.com/blogs/chris/introducing-max-creation-graphsPyQt UI in 3ds Max 2014 ExtensionChristopher Diggins<p>Chances are you are reading this because you want to write some UI for 3ds Max using Python. Because 3ds Max is fundamentally a Win32 application there are some challenges to overcome:</p> <ol> <li>Make your PyQt window is a proper child windows of 3ds Max</li> <li>Make sure that Python doesn't collect your objects</li> <li>Making sure that accelerators are disabled when your Widget has the focus</li> </ol> <h2>Making PyQt Windows a Child of 3ds Max</h2> <p>Digia provides a Qt module for C++ called <a href="http://doc.qt.digia.com/solutions/4/qtwinmigrate/winmigrate-walkthrough.html">QtWinMigrate</a> that was designed specifically to support mixing Qt with native Win32 UI. This <a href="/blogs/chris/embedding-qt-content-in-a-3ds-max-dockable-frame">works very well in C++</a> but unfortunately is not available by default in the PyQt or PySide packages. Luckily Blur studios wrapped make this package available in their <a href="https://code.google.com/p/blur-dev/downloads/list">binary PyQt distribution</a>. If you need to build it from sources yourself the <a href="https://github.com/glennra/PyQtWinMigrate">SIP sources can also be found online</a>.</p> <p>Once installed (note: I didn't install the Blur plug-ins. I have no idea how that could affect Python in the 3ds Max 2014 extension) you have to tell the 3ds Max Python engine where the PyQt module is. This can be done by updating the PYTHONPATH folder to point to the folder containing your Blur PyQt installation. For example I installed the Blur Qt into my regular Python installation folder, I set the PYTHONPATH user environment variable to "C:\Python27\Lib\site-packages".&nbsp; If you already have the PYTHONPATH variable you can append it to the list of paths, separating it from the others using a semicolon. If 3ds Max is running you will have to restart it before this change can take effect.</p> <p>A simple test to see if 3ds Max Python can find the PyQt is to write:<br />python.executeFile "demoPyVersionTool.py"</p> <p>On my system the result is:</p> <p>&nbsp;&nbsp;&nbsp; 3ds Max 2014 path environment variable c:\\program files\\autodesk\\3ds max 2014\\<br />&nbsp;&nbsp;&nbsp; MaxPlus module False<br />&nbsp;&nbsp;&nbsp; PyQt QT version 4.8.3<br />&nbsp;&nbsp;&nbsp; PyQt module True<br />&nbsp;&nbsp;&nbsp; PyQt version snapshot-4.9.5-9eb6aac99275<br />&nbsp;&nbsp;&nbsp; PySide module False<br />&nbsp;&nbsp;&nbsp; Python prefix C:\Program Files\Autodesk\3ds Max 2014\python<br />&nbsp;&nbsp;&nbsp; Python version 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)]<br />&nbsp;&nbsp;&nbsp; os module True<br />&nbsp;&nbsp;&nbsp; sys module True<br />&nbsp;&nbsp;&nbsp; #success<br />&nbsp;&nbsp;&nbsp;</p> <p>Once all of this is done you have to do a bit of extra work to get the 3ds Max HWND from the MaxPlus API because it is exposed as a SWIG object, and not a plain int. Here is a snippet of code that illustrates how to do this.</p> <pre class="prettyprint">import MaxPlus, ctypes from PyQt4 import QtGui, QtCore, QtWinMigrate def getMaxHwnd(): mem = long(MaxPlus.Win32.GetMAXHWnd()) return ctypes.c_longlong.from_address(mem).value class MaxWidget(QtGui.QMainWindow): def __init__(self): self.parent = QtWinMigrate.QWinWidget(getMaxHwnd()) QtGui.QMainWindow.__init__(self, self.parent)<br />&nbsp;</pre> <h2>Make sure that Python doesn't collect your objects</h2> <p>There is not much documentation on how to assure that Python doesn't collect your PyQt objects, and to be honest I don't know exactly what the best practice should be. The general principle is that Python needs to see at least one active reference to an object so that it doesn't collect it. For this purpose I use a class member variable to track custom high-level PyQt widgets that I create which I remove when the widget is closed. </p> <pre class="prettyprint">class _Widgets(object): _instances = [] class MaxWidget(QtGui.QMainWindow): def __init__(self): self.parent = QtWinMigrate.QWinWidget(getMaxHwnd()) QtGui.QMainWindow.__init__(self, self.parent) _Widgets._instances.append(self) def closeEvent(self, event): if self in _Widgets._instances: _Widgets._instances.remove(self)<br />&nbsp;</pre> <h2>Making sure that accelerators are disabled when your Widget has the focus</h2> <p>Another challenge with UI code in 3ds Max is that the main window of 3ds Max will interpret most key-presses as shortcut keys. When you have an edit field in a Python UI this can pose some obvious problems. Normally in regular 3ds Max UI programming we can use the DisableAccelerators API call to temporarily disable shortcut keys. The problem with PyQt is knowing exactly when to make this call.</p> <p>Intuitively we may think that overriding the Qwidget.focusInEvent() would work, but when using PyQt with Win32, the event is not triggered automatically when switching from a non-PyQt managed window to a PyQt window. The best approach that I have been able to come up with is to install an event filter of the QApplication instance that previews all mouse clicks. If the QApplication exposed to Python sees a mouse click, then we assume that a PyQt window has gained focus and we can disable accelerators. It&rsquo;s a bit hacky, and I'm sure the more experienced Python programmers out there can suggest an alternative, but this is the best I could find for now, at least until we can make improvements to the core.</p> <p>Putting this together with the other techniques here is a complete code example</p> <pre class="prettyprint"># To execute from MAXScript (if in your &lt;maxroot&gt;/scripts/python folder. # python.executeFile "auDemoPyQt.py" import MaxPlus import ctypes from PyQt4 import QtGui, QtCore # Requires PyQt4 binaries from Blur studios https://code.google.com/p/blur-dev/downloads/list from PyQt4 import QtWinMigrate # Get or create the application instance as needed # This has to happen before any UI code is triggered app = QtGui.QApplication.instance() if not app: app = QtGui.QApplication([]) def getMaxHwnd(): ''' Get the HWND of 3ds Max as an int32 ''' mem = long(MaxPlus.Win32.GetMAXHWnd()) return ctypes.c_longlong.from_address(mem).value class _Widgets(object): ''' Used to store all widget instances and protect them from the garbage collector ''' _instances = [] class _FocusFilter(QtCore.QObject): ''' Used to filter events to properly manage focus in 3ds Max. This is a hack to deal with the fact that mixing Qt and Win32 causes focus events to not get triggered as expected. ''' def eventFilter(self, obj, event): # We track any mouse clicks in any Qt tracked area. if event.type() == QtCore.QEvent.MouseButtonPress: print "Mouse down", obj elif event.type() == 174: # QtCore.QEvent.NonClientAreaMouseButtonPress: print "Non-client button press", obj else: return False MaxPlus.CUI.DisableAccelerators() return False class MaxWidget(QtGui.QMainWindow): # Note: this does not work automatically when switching focus from the rest of 3ds Max # to the PyQt UI. This is why we have to install an event filter. def focusInEvent(self, event): print "Focus gained on MaxWidget" MaxPlus.CUI.DisableAccelerators() def __init__(self): print "Creating MaxWidget" self.parent = QtWinMigrate.QWinWidget(getMaxHwnd()) QtGui.QMainWindow.__init__(self, self.parent) _Widgets._instances.append(self) # Install an event filter. Keep the pointer in this object so it isn't collected, and can be removed. self.filter = _FocusFilter(self) app.installEventFilter(self.filter) def closeEvent(self, event): print "Closing MaxWidget" if self in _Widgets._instances: _Widgets._instances.remove(self) # Very important, otherwise the application event filter will stick around for app.removeEventFilter(self.filter) class MyWidget(QtGui.QWidget): def btnPressed(self): print "Button pressed" if self.parent(): self.parent().setFocus() def __init__(self): QtGui.QWidget.__init__(self) self.topLayout = QtGui.QGridLayout() self.nextLayout = QtGui.QGridLayout() self.textEdit = QtGui.QTextEdit() self.textEdit.setText("Hello world") self.btn = QtGui.QPushButton("Apply") self.btn.pressed.connect(self.btnPressed) self.nextLayout.addWidget(self.textEdit) self.nextLayout.addWidget(self.btn) self.topLayout.addLayout(self.nextLayout, 0, 0) self.setLayout(self.topLayout) def main(): main = MaxWidget() w = MyWidget() main.setCentralWidget(w) main.show() if __name__ == '__main__': main()</pre>Wed, 11 Dec 2013 19:47:02 UTChttp://area.autodesk.com/blogs/chris/pyqt-ui-in-3ds-max-2014-extensionThe 3ds Max Gunslinger and yes I read your Crash Error Reports (CER&#039;s)Christopher Diggins<p>This year we had our first ever "gunslinger" event for 3ds Max. This was an opportunity for members of the development team (developers, QA, design, and product manager) to meet a cross-section of 3ds Max users and discuss their ideas, questions, and concerns. We invited several prominent members of the 3ds Max community to meet with the 3ds Max team in the Montreal office for two and a half days. For some it was also an opportunity to meet with the new 3ds Max product manager <a href="/blogs/eddie">Eddie Perlberg</a>, though many customers already know him through his work as an application engineer, his blog, or via his classes at Autodesk University.<br /><br />During the event we discussed the 3ds Max product development process (e.g. how we use the Scrum development methodology and the legal repercussions that prevent us from talking publicly about current or future feature development). Hopefully they better understood why we are sometimes vague about what we are doing, and why it seems to take long (from a&nbsp; cutsomer perspective) to start on new features. We also spent a lot of time learning how they use the product, what their pain points are, and what they want to do more easily in the future.</p> <p>One question a lot of them had was how we choose what we work on. What surprised me to learn was that many customers didn't realize how influential CER data is for us when fixing bugs and improving stability. A CER (Crash Error Report) is the data sent to 3ds Max when a crash occurs and a dialog pops-up asking if you want to send the data to 3ds Max. We have an official description of the <a href="http://usa.autodesk.com/adsk/servlet/index?siteID=123112&amp;id=7047344&amp;linkID=9241177">CER workflow on Autodesk.com</a>.<br /><br />Autodesk receives hundreds of thousands of CER reports annually. This means that we can't follow-up on inidividual CER reports, and instead rely heavily on data-mining techniques. The data goes to a database and is auto-triaged based on the module and auto-linked to related crashes. When patterns emerge, CERs are grouped into defects which are tehen submitted by the QA team to the development team. So as a developer I often see CERs once there are a group in a certain module (e.g. function or DLL) and assigned to a defect, which is usually a long time after it is submitted. At that point I can end up reading hundreds of CER reports one by one trying to find patterns.<br /><br />Many people realize that 3ds Max 2014 is a very stable release which is due in large part to us working from data provided to us from CER reports. This has helped us identify, prioritize, and fix problems. The most useful thing you can do is provide us with steps that can consistently reproduce the crash. A description of the problem and the worfklow can also help (one of our users keeps us entertained by describing his problems in Haiku). Yes, we do get some data on what you were doing, but the technology is far from perfect. However, even without anything else just clicking "send" with no data still helps us to identify the modules that need to be reviewed more carefully. <br /><br /></p>Sun, 27 Oct 2013 16:41:28 UTChttp://area.autodesk.com/blogs/chris/the-3ds-max-gunslinger-and-yes-i-read-yourcrash-error-reports-cer039sADN DevDays Conference in Las Vegas at AU and a New 3ds Max SDK BlogChristopher Diggins<p>The Autodesk Developer Network (ADN) is going to be hosting another DevDays co-located at Autodesk University in Las Vegas on Monday December 2nd this year. I'll be there to talk about the new Python API in 3ds Max. For more information on attending you can see <a href="http://around-the-corner.typepad.com/adn/2013/10/adn-devdays-au-las-vegas-2013.html">Cyrille Fauvel's blog</a> or <a href="http://au.autodesk.com/las-vegas/pre-conference/adn-conference-devlab">register directly here</a>. In addition I will be available (along with ADN and other members of the engineering team) to answer your SDK questions and help you resolved technical problems during the <span class="s4-b-lh19 mdGrey">ADN DevLab programming workshop on the second day. <br /></span></p> <p><span class="s4-b-lh19 mdGrey">The other piece of good news (which I apologize for being late to announce) is that Kevin Vandecar, 3ds Max developer consultant at ADN, has launched a new <a href="http://getcoreinterface.typepad.com/blog/2013/09/welcome-to-the-new-3ds-max-customization-and-programming-blog.html">blog for 3ds Max SDK users</a> called amusingly enough "GetCoreInterface". Hopefully this will make up for the lack of activity on my own blog.&nbsp; </span></p> <p><span class="s4-b-lh19 mdGrey"><br /></span></p>Thu, 17 Oct 2013 18:40:18 UTChttp://area.autodesk.com/blogs/chris/adn-devdays-conference-in-las-vegas-at-au-and-a-new-3ds-max-sdk-blogM&amp;E Scripting and SDK Channel on YouTubeChristopher Diggins<p>Recently the video learning team launched a new learning channel (<a href="http://www.youtube.com/user/ScriptingSDKHowTos/videos">http://www.youtube.com/user/ScriptingSDKHowTos/videos</a>) dedicated to SDK and scripting users. Right now we have videos on FBX, Maya, MotionBuilder and ICE. I hear that they are working on some 3ds Max videos, so if you do any SDK/scripting development I suggest subscribing!</p> <p>Here are a few samplers:</p> <p>http://www.youtube.com/watch?v=CvRgN6m5XuU</p> <p>http://www.youtube.com/watch?v=eXFGeZZbMzQ</p> <p>http://www.youtube.com/watch?v=OgT1B69BqWg</p> <p>http://www.youtube.com/watch?v=1PF-dBjsqOM</p> <p>One of the great things about the video channels is that they are a great way to enter into a dialogue with our subject matter experts and make suggestions for future learning materials.</p> <p></p>Sat, 12 Oct 2013 12:16:27 UTChttp://area.autodesk.com/blogs/chris/mampe-scripting-and-sdk-channel-on-youtubeAutodesk Exchange Apps Portathon is happening on September 13th.Christopher Diggins<p>The <a href="http://apps.exchange.autodesk.com/en">Autodesk Exchange store</a> provides a broad range of Autodesk&reg; approved extensions for users of several Autodesk products such as 3ds Max and Maya. If you are a developer of extensions for Autodesk products it is a great way to reach more potential users. For more information on publishing content to app-exchange see <a href="http://apps.exchange.autodesk.com/en/Publisher/Description">http://apps.exchange.autodesk.com/en/Publisher/Description</a>.</p> <p>To support and encourage developers to port existing scripts and plug-ins to the app-exchange, Autodesk is hosting a portathon, a 48 hour virtual web based coding event runs through September 13 and 14, 2013.This is a community event where you&rsquo;ll have the opportunity to work closely with Autodesk engineers in real time and meet hundreds of other Autodesk software partners from around the world.&nbsp; It is all designed to help you get your apps ready and published on Autodesk Exchange Apps.</p> <p>There&rsquo;s no cost to join the Portathon, but there is a reward.&nbsp; For all new apps submitted to the Autodesk Exchange Apps store by midnight on September 14, 2013 and accepted for publication in the store by October 31, 2013, you will receive US$ 100 per app (for up to 5 apps &ndash; US$ 500 total).</p> <p>Don't delay - join well over 100 developers in getting the help you may need to get your apps published. For details visit: <a href="http://autode.sk/15DjZpq">http://autode.sk/15DjZpq</a></p>Tue, 10 Sep 2013 17:29:06 UTChttp://area.autodesk.com/blogs/chris/autodesk-exchange-apps-portathon-is-happening-on-september-13th3ds Max and Stage AutomationChristopher Diggins<p>Stage automation is a growing industry that plays an important role in live entertainment events from music shows to Cirque du Soleil. What may come as a surprise is that thanks to a plug-in from Stage Technologies 3ds Max is playing an increasingly important role in designing, simulating, and visualizing automation for live events.</p> <p><a href="http://www.stagetech.com/press/sculptor-animation-toolkit">Stage Technologies</a> is an Australian company specializing in live event automation, they sell a number products for managing and controlling numerous types of live event automations. Among their products is a 3ds Max plug-in called <a href="http://www.stagetech.com/sculptor-toolkit">Sculptor Animation Toolkit</a>. Sculptor toolkit turns 3ds Max into a tool for designing and preview automation and to receive feedback on what movements are impossible or dangerous. Once ready Sculptor Toolkit data can be sent directly from 3ds Max to the <a href="http://www.stagetech.com/echameleon">eChameleon automation software</a>.</p> <p>As an example Sculptor Toolkit can be used to define a trolley that travels along a track, add a revolving ring hanging from it, then add some winches below the revolving ring as linear axes; these winches might then act as pickups in a larger bridled system. Flight paths, either drawn or sourced from recorded joystick data can be imported and supplementary feedback is provided to the operator when refining these paths, ensuring the flown move will run safely.</p> <p>The following video shows Sculptor Toolkit in action.</p> <p>http://www.youtube.com/watch?v=t3XW2Pq8LxQ</p> <p>3ds Max and the Sculptor Toolkit have been used together to design and visualize live event productions from <a href="http://www.stagetech.com/Radiohead-control">RadioHead</a> to the <a href="http://www.stagetech.com/Pan_American_Games">Pan-American games opening ceremony</a> to animating a giant robotic Gorilla for an upcoming musical about King Kong.</p> <p>http://vimeo.com/57498670</p> <p>For more information on Sculptor Animation Toolkit see <a href="http://www.stagetech.com/press/sculptor-animation-toolkit">http://www.stagetech.com/press/sculptor-animation-toolkit</a>. <br /><br /></p>Mon, 06 May 2013 14:47:58 UTChttp://area.autodesk.com/blogs/chris/3ds-max-and-stage-automation3ds Max and Flash Working TogetherChristopher Diggins<p>You may be familiar with <a href-:http:="" zynga="" com="" game="" farmville-two="">FarmVille 2</a>: it is currently the second most popular app on FaceBook with over <a href="http://www.appdata.com/leaderboard/apps?metric_select=mau_estimate&amp;style=classic">40,000,000 estimated monthly users</a> (as of the date of this posting). What you may not know is that FarmVille is built using the Flare3D engine and 3ds Max.</p> <p>The following video talks about the role of 3ds Max in FarmVille 2:</p> <p>http://www.youtube.com/watch?v=8iBjwLHyag4</p> <p>This next video talks about the role of Flare3D in FarmVille 2:</p> <p>http://www.youtube.com/watch?v=nnNKko2ELKQ</p> <p><a href="http://www.flare3d.com/">Flare3D</a> is a 3D engine that leverages a relatively new Flash technology called Stage3D (previously known as Molehill) to deliver GPU accelerated 3D graphics called Stage 3D. You can try Flare3D and the <a href="http://www.flare3d.com/downloads/">3ds Max exporter for free here</a>. The following video demonstrates the Flare3D exporter for lightmaps:</p> <p>http://www.youtube.com/watch?v=IG5acCdnz00</p> <p>A popular open-source 3D engine for Flash is <a href="http://away3d.com/">Away3D</a>. The following video is the Away3D Demo reel presented at GDC:</p> <p>http://vimeo.com/62962084</p> <p>Zynga, the makers of FarmVille 2, use Away3D in another popular Facebook game called <a href="http://away3d.com/showcase/detail/cafe_world">Caf&eacute; World</a>. Away3D was also used to build interactive 3D web applications to promote the <a href="http://megane.renault.co.uk/uk/#/3d.html">Renault Megane</a> and the <a href="http://www.nissan-stagejuk3d.com/">Nissan Juke</a>.</p> <p>[EDIT: Rob Bateman from Away3D suggest that people also check out the <a href="http://www.nissan.co.uk/GB/en/vehicles/crossovers/juke/personalisation.html">Nissan Juke 3D configurator</a> as it better showcases Away3D functionality, but unfortunately for me it only works on Google Chrome.].</p> <p>One use case of 3ds Max and Away3D that I found particularly interesting was <a href="https://itunes.apple.com/au/app/the-clarence/id576987034?mt=8">this iPad app</a> (built with Adobe AIR) for a <a href="http://away3d.com/showcase/detail/the_clarence">condo project called the Clarence</a>.</p> <p>There is a <a href="http://www.adobe.com/devnet/flashplayer/articles/away3d-autodesk3dsmax.html">tutorial on the Adobe website</a> for step by step instruction on how to create an interactive 3D application for 3ds Max using Away3D. If you want you can also download an Away3D exporter project&nbsp; <a href="http://code.google.com/p/awd/">Away3D file format (AWD) project on Google code</a>.</p>Tue, 23 Apr 2013 01:04:08 UTChttp://area.autodesk.com/blogs/chris/3ds-max-and-flash-working-together3ds Max SDK and MAXScript CHMs now availableChristopher Diggins<p>We discontinued CHM support for SDK documentation two releases ago in order to focus on HTML-based help.&nbsp;<span style="line-height: 1.5em;">However since many users asked us for CHMs on the 3ds Max feedback forums:&nbsp;</span><a href="http://3dsmaxfeedback.autodesk.com/forums/80701-sdk-and-scripting-enhancements/suggestions/2099795-compiled-maxscript-reference-chm-" style="line-height: 1.5em;">http://3dsmaxfeedback.autodesk.com/forums/80701-sdk-and-scripting-enhancements/suggestions/2099795-compiled-maxscript-reference-chm-</a>&nbsp;we have decided to bring back CHM for the 3ds Max SDK and MAXScript.</p> <p>Check out the new help on our updated SDK help page at: <a href="http://www.autodesk.com/me-sdk-docs">http://www.autodesk.com/me-sdk-docs</a>.&nbsp;</p>Sat, 20 Apr 2013 13:47:26 UTChttp://area.autodesk.com/blogs/chris/3ds-max-sdk-and-maxscript-chms-now-availableSell or Share your Plug-ins, Tutorials, or other Content for 3ds Max and Maya via the Autodesk ExchangeChristopher Diggins<p>With the release of Maya 2014 and 3ds Max 2014 the Autodesk Exchange site makes it easier for plug-in, content, and tutorial developers to distribute and sell their content more easily to Autodesk customers.</p> <ul> <li>The Autodesk Exchange for 3ds Max can be found at: <a href="http://apps.exchange.autodesk.com/3DSMAX/Home/Index">http://apps.exchange.autodesk.com/3DSMAX/Home/Index</a></li> <li>The Autodesk Exchange for Maya can be found at: <a href="http://apps.exchange.autodesk.com/MAYA/Home/Index">http://apps.exchange.autodesk.com/MAYA/Home/Index</a></li> </ul> <p>Both Maya 2014 and 3ds Max 2013 have direct links to the exchange app store from within the product under the help menu. In Maya go to "Help &gt; Exchange Apps" in the main menu. In 3ds Max go to "Help &gt; Autodesk Product Information &gt; Exchange Apps".</p> <p>According to the <a href="http://usa.autodesk.com/adsk/servlet/index?id=17183245&amp;siteID=123112">Autodesk Exchange developer center</a> "apps" aren't restricted to plug-ins, and can be anything a customer will find useful. For example:</p> <ul> <li>&nbsp;&nbsp;&nbsp; Plug-ins</li> <li>&nbsp;&nbsp;&nbsp; Standalone applications</li> <li>&nbsp;&nbsp;&nbsp; Training tutorials</li> <li>&nbsp;&nbsp;&nbsp; E-books</li> <li>&nbsp;&nbsp;&nbsp; Content</li> </ul> <p>Note that at the current time there is no cost to sign-up and Autodesk is currently taking no commission, but may do so in the future. For more information on that <a href="http://usa.autodesk.com/adsk/servlet/item?siteID=123112&amp;id=20149725">see the Publisher FAQ</a>.</p> <p>If you have enough information and want to get started publishing your content for 3ds Max or Maya, you can go directly the following links:</p> <ul> <li>3ds Max -<a href="http://apps.exchange.autodesk.com/3DSMAX/Home/Index"> </a><a href="http://apps.exchange.autodesk.com/Publisher/Description?productline=3DSMAX">http://apps.exchange.autodesk.com/Publisher/Description?productline=3DSMAX</a><a href="http://apps.exchange.autodesk.com/3DSMAX/Home/Index"></a></li> <li>Maya - <a href="http://apps.exchange.autodesk.com/Publisher/Description?productline=MAYA">http://apps.exchange.autodesk.com/Publisher/Description?productline=MAYA</a></li> </ul> <p>Happy content publishing!</p>Fri, 19 Apr 2013 14:04:13 UTChttp://area.autodesk.com/blogs/chris/sell-or-share-your-plug-ins-tutorials-or-content-for-3ds-max-and-maya-via-the-autodesk-exchangeEmbedding Qt Content in a 3ds Max Dockable FrameChristopher Diggins<p>The 3ds Max API provides a custom Windows control called a CUIFrame that allows a plug-in developer to create dockable content. As part of a recent investigation I decided to figure out how to embed a Qt C++ dialog CUIFrame in CUIcontent. I created a helper class called "DockableWindow" that can be used as follows:</p> <pre class="code">DockableWindow* DoStuff() { DockableWindow* dock = DockableWindow::Create(_T("My QT Demo")); HWND h = dock-&gt;GetHWND(); dlg = new QWinWidget(h); Ui::Dialog().setupUi(dlg); dock-&gt;SetWidget(dlg); return dock; } </pre> <p>Here is the implementation of the DockableWindow class.</p> <pre class="code">class DockableWindow : public CUIPosData, public CUIFrameMsgHandler { HWND h; ICUIFrame* frame; QWidget* w; CUIPosData posData; DockableWindow(HWND hwndCuiFrame) : h(hwndCuiFrame), w(NULL), frame(NULL) { frame = ::GetICUIFrame(h); frame-&gt;InstallMsgHandler(this); } void ResizeFrameToContent() { RECT r = {0}; if (w == NULL) return; GetWindowRect(h, &amp;r); MoveWindow( h, r.left, r.top, w-&gt;width(), w-&gt;height(), TRUE ); } void ResizeContentToFrame() { if (w == NULL) return; RECT r = {0}; GetWindowRect(h, &amp;r); int width = r.right - r.left; int height = r.bottom - r.top; w-&gt;resize(width, height); } virtual int GetWidth(int sizeType, int orient) { switch (sizeType) { case CUI_MIN_SIZE: return 50; case CUI_MAX_SIZE: return 10000; } return w-&gt;width(); } virtual int GetHeight(int sizeType, int orient) { switch (sizeType) { case CUI_MIN_SIZE: return 50; case CUI_MAX_SIZE: return 10000; } return w-&gt;height(); } public: enum DockFlags { Top = 1 &lt;&lt; 0, Bottom = 1 &lt;&lt; 1, Left = 1 &lt;&lt; 2, Right = 1 &lt;&lt; 3, Horizontal = Left | Right, Vertical = Top | Bottom, All = Horizontal | Vertical, }; virtual ~DockableWindow() { ::ReleaseICUIFrame(frame); delete w; } static DockableWindow* Create(MCHAR* name, DockFlags pos = All, DWORD initialPos = 0, bool isDockedInitially = false, bool resizable = true, bool visible = true) { HWND h = ::CreateCUIFrameWindow( ::GetCOREInterface()-&gt;GetMAXHWnd(), name, 0, 0, 0, 0); if (!h) return NULL; DockableWindow* r = new DockableWindow(h); ICUIFrame* f = r-&gt;GetICUIFrame(); DWORD flags = pos | CUI_FLOATABLE; if (resizable) flags |= CUI_SM_HANDLES; f-&gt;SetPosType(flags); if (isDockedInitially) r-&gt;Dock(initialPos); f-&gt;Hide(visible ? FALSE : TRUE); return r; } virtual int ProcessMessage (UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case CUI_POSDATA_MSG: { CUIPosData **cpd = (CUIPosData **)lParam; cpd[0] = this; return TRUE; } case WM_SIZING: ResizeContentToFrame(); return FALSE; } return FALSE; } bool HasWidget() { return GetWidget() != NULL; } QWidget* GetWidget() { return w; } void SetWidget(QWidget* w) { delete(this-&gt;w); this-&gt;w = w; if (w == NULL) return; w-&gt;move(0, 0); ResizeFrameToContent(); w-&gt;show(); } void Dock(DWORD location) { if (location &amp; Top) GetCUIFrameMgr()-&gt;DockCUIWindow(h, Top); else if (location &amp; Bottom) GetCUIFrameMgr()-&gt;DockCUIWindow(h, Bottom); else if (location &amp; Left) GetCUIFrameMgr()-&gt;DockCUIWindow(h, Left); else if (location &amp; Right) GetCUIFrameMgr()-&gt;DockCUIWindow(h, Right); } void Float() { GetCUIFrameMgr()-&gt;FloatCUIWindow(h); } HWND GetHWND() { return h; } ICUIFrame* GetICUIFrame() { return frame; } }; </pre> <p>For more information see the <a href="http://doc.qt.digia.com/solutions/qtwinmigrate/qwinwidget.html">QWinWidget</a> Qt class and the following 3ds Max SDK classes:</p> <ul> <li><a href="http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/cpp_ref/class_c_u_i_pos_data.html">CUIPosData</a></li> <li><a href="http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/cpp_ref/class_c_u_i_frame_mgr.html">CUIFramMgr</a></li> <li><a href="http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/cpp_ref/class_c_u_i_frame_msg_handler.html">CUIFrameMsgHandler</a></li> <li><a href="http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/cpp_ref/class_i_c_u_i_frame.html">ICUIFrame</a></li> </ul>Thu, 04 Apr 2013 16:22:18 UTChttp://area.autodesk.com/blogs/chris/embedding-qt-content-in-a-3ds-max-dockable-frame