Actor COMP and Python: Difference between pages

From Derivative
(Difference between pages)
Jump to navigation Jump to search
mNo edit summary
 
mNo edit summary
 
Line 1: Line 1:
{{Summary
__TOC__
|opFamily=COMP
== Python In TouchDesigner ==
|opType=actorCOMP
TouchDesigner uses [https://www.python.org/ Python] for scripting tasks. A custom Python build is included, with most of the features of a standard Python installation and a huge number of tools and utilities specific to working in the software.  
|opLabel=Actor
* Quick Start: [[Introduction to Python Tutorial|Tutorial: Introduction to Python in TouchDesigner]].
|opClass=actorCOMP_Class
* Common script examples: [[Python Tips]]  
|opFilter=False
* List of [[Python Classes and Modules|TouchDesigner Python Classes and Modules]]  
|opLicense=Non-Commercial
* Index of all Python pages in this wiki: [[:Category:Python_Reference|Python Reference]]
|short=An Actor COMP is analogous to a body (or bodies) in a physics system.
|long=An Actor COMP is analogous to a body (or bodies) in a physics system. An Actor COMP must be used in conjunction with a physics solver: either a [[Bullet Solver COMP]] or [[Nvidia Flex Solver COMP]], which in turn is analogous to the world/simulation that the actors/bodies operate in. An Actor COMP can either be static, meaning it is not affected by any forces in the simulation and cannot move (ie. has infinite mass), or it can be dynamic, meaning it is moved by forces and collides with other bodies (either static or dynamic) in the world.


See also: [[Flex]], [[Bullet Dynamics]], [[Bullet Solver COMP]], [[Force COMP]], [[Constraint COMP]], [[Bullet Solver CHOP]], [[Nvidia Flex Solver COMP]], [[Nvidia Flex TOP]].|opCategories=
In addition, selecting '''Help -> Python Examples''' in the TouchDesigner UI takes you to the <code>PythonExamples.toe</code> file with 100+ working examples.
}}
{{OPSection
|opFamily=COMP
    |sectionName=Usage
    |sectionSummary=
    |items={{OPSubSection
|opFamily=COMP
    |sectionName=Actors in Bullet
    |sectionSummary=Static bodies can be concave or convex, but dynamic bodies must be convex. However, dynamic collision shapes can be compound, meaning it is a collision shape made of other collision shapes. So, a concave collision shape can be created in the dynamic case by building it out of a group of convex shapes. This can be done using multiple SOPs. Each SOP must be convex, but combination of the SOPs does not need to be. If Automatic mode is selected, then a compound collision shape will be created from these SOPs.


All bodies in an Actor COMP have a corresponding collision shape. The collision shape is what determines how objects will collide with one another, and it is important to note that what is seen in the viewer/render will not necessarily directly match the collision shape.
== Learning Python ==
If you don't know Python, here are some good resources for learning:
* [https://docs.python.org/3/tutorial/index.html The official Python tutorial]
* [https://docs.python-guide.org/intro/learning/ Python Learning Resources]
* [https://www.pcworld.com/article/3287981/best-python-courses.html List of online Python courses]
* [http://www.codeacademy.com General programming courses at codeacademy.com]
* [http://overapi.com/python Python cheat sheet]
* [https://www.freecodecamp.org/news/freecodecamp-python-courses-ranked-from-best-to-worst/ Python at freeCodeCamp]
* alphamoonbase's tips and tricks: [https://derivative.ca/community-post/python-tipsntricks Part 1], [https://derivative.ca/community-post/python-tipsntricks-2 Part 2], [https://derivative.ca/community-post/python-tipsntricks-3 Part 3] - real-world python-in-TouchDesigner experience


Collision shapes are created using SOPs, either through the "Collision SOPs" parameter or by putting them inside the Actor COMP itself. If the "Collision SOPs" parameter is filled in, then the Actor COMP will create a single body from all the SOPs at that given paths (if the path is a COMP then it will recursively grab all the SOPs in the COMP). If there is nothing filled in for the "Collision SOPs" parameter, then the Actor COMP will instead recursively search inside itself for any SOPs that have both their display and render flags on. The Actor COMP will create a single body and corresponding collision shape from these SOPs.
== Python Classes and Modules Available in TouchDesigner ==
TouchDesigner includes all the modules in a [https://docs.python.org/3.11/library/ standard Python installation] plus the following:
=== <code>td</code>: TouchDesigner's Main Python Module ===
'''All [[Td Module|td module]] members and methods are available in scripts, expressions, and the textport.''' There is no need to import the module or its members explicitly. This is especially important in expressions, which don't allow import statements.  


There are several options when it comes to creating a collision shape out of the SOPs. These options can be chosen from the "Collision Shape" parameter. For instance, the option "Oriented Bounding Box" will create a minimum volume bounding box around the selected SOPs.
The following can be found in the <code>td</code> module:
* '''[[Td Module|Main TouchDesigner utilities]]''' - the most basic starting points for interacting with TouchDesigner, such as <code>me</code> and <code>op()</code>.
* '''[[Python Classes and Modules#Helper_Classes|TouchDesigner Python helper classes]]''' - important helper objects used to organize functions and information pertaining to a specific part of TouchDesigner.
* '''[[Python Classes and Modules#Operator_Related_Classes|Operator related classes]]''' - every [[Operator]] in TouchDesigner has an associated Python class in the <code>td</code> module. Their wiki pages can be accessed by clicking on the Python Help button in their [[Parameter Dialog|parameter dialog]]. There are also a number of associated Python objects that are used when working with Operators.  
* '''[[Python Classes and Modules#Standard_Python_Modules|Useful standard Python modules]]''' - the <code>td</code> module also automatically imports a number of helpful standard modules (e.g. <code>math</code>), allowing them to be accessed in expressions through their namespace.


To create multiple bodies, use the instancing on the "Instance" page of the Actor COMP. This will create any number of identical bodies, each with their own identical collision shape. Currently there is no way to create multiple non-identical bodies in a single Actor COMP.  
=== TouchDesigner Utility Modules ===
TouchDesigner also contains utility modules for advanced Python programming. Utility modules are not imported into the <code>td</code> module automatically. Instructions for their use can be found on their wiki pages.
* '''[[Python Classes and Modules#TouchDesigner_Utility_Modules and Python Utilities|List of Python Utility Modules and Python Utilities]]'''.


Bodies are initialized using the "Initialize Actor" parameter, so if any changes are made to the SOPs that create the bodies, then the Actor COMP must be reinitialized. Bodies will automatically be re-initialized if the Kinematic State, Shape, or Center of Mass is changed.  
=== 3rd Party Packages ===
TouchDesigner includes a number of 3rd party Python packages that are generally useful when working with the software. These are not included in the <code>td</code> module so must be imported explicitly.
* '''[[Python Classes and Modules#3rd_Party_Packages|List of 3rd party Python Packages]]'''.


Transforms can be applied to an Actor COMP using the Xform and Pre-Xform pages, much like on a Geometry COMP or Camera COMP. The transforms on the Xform and Pre-Xform pages create the initial transform of the actor in the simulation, but they can also be used to modify the transform of an actor during a simulation. Changing scale on either page will require a reinitialization of the actor since it changes the collision shape itself. Modifying any of the transforms while instancing will automatically reinitialize the actor.
=== Installing Custom Python Packages ===
Part of the great power of Python is its access to the countless number of modules that have been created. If you want to use modules that are not included in the above, use the following steps:


Actor COMPs cannot be nested; however, Actor COMPs can be nested inside Geometry COMPs and vice versa. Geometry COMPs with a nested Actor COMPs cannot have any scale transform; however, Geometry COMPs nested inside an Actor COMP can have scale. An Actor COMP nested inside Geometry COMPs will use their transform only when it is initialized. Therefore, any changes to the transform of these Geometry COMPs will require a reinitialization of the Actor COMP.
Note: When adding your own version for a package that is already shipped with TouchDesigner, you might encounter unexpected behaviors.
}}<!--
Many of our internal tools and palette components rely on NumPy and/or OpenCV. '''Loading different versions of Numpy and/or OpenCV is at your own risk.'''
-->{{OPSubSection
Some other issue could be with the following: considering a Package A with a dependency B, if updating your sys.path cause a different version of dependency B to load first, it could cause issues with Package A.
|opFamily=COMP
    |sectionName=Actors in Flex
    |sectionSummary=[[Flex]] actors can either be fluid particles, a fluid particle emitter, or a static shape.  


Static shapes in Flex are built in the same way that concave (ie. static) shapes are built in Bullet. Static shapes require a triangle mesh SOP to build up their collision shape. However, box/sphere collision shape options can also be used to create a bounding box/sphere of the collision shape SOP.
==== Windows ====
#Install a parallel copy of the same version of Python to the hard disk. The current version of Python shipped with TouchDesigner is 3.11. It can be found [https://www.python.org/downloads/ here]. Use the most recent subversion of 3.11.
##Alternatively, you can use a Python package and environment manager, [https://derivative.ca/community-post/tutorial/anaconda-managing-python-environments-and-3rd-party-libraries-touchdesigner such as Anaconda].
#Install the package to the parallel python installation, following its normal installation procedure.
#Launch Python and import the module manually to make sure there are no errors outside of the TouchDesigner context.


Fluid particles behave much the same way as instancing on a Bullet actor. The number of fluid particles is equal to the number of instances created from an instance OP. The instance parameters are used to give the particle an initial transform, but once the simulation is running the transform is updated from the simulation results.
Once the module is successfully installed, you can import it in TouchDesigner following those next steps:


One key difference of a fluid particle Actor COMP is that no SOP is needed to create a fluid particle since their size/behaviour is defined through the simulation parameters on the [[Nvidia Flex Solver COMP]]. A SOP in the Actor COMP can be used to the render/display the positions of the particles. Alternatively, the particle positions can be fetched using the [[Nvidia Flex TOP]].
Under the Edit->Preferences menu, tick "Add External Python to Search Path". You can add the search path by modifying the Preference labelled "Python 32/64 bit Module Path". Multiple paths are separated by semicolons (<code>;</code>).  


Fluid emitters add particles to the scene at the emission point (ie. the transform of the Actor COMP). Particles are added up until the emission maximum is reached, at which point emission particles will be recycled from already existing particles.
Finally you can modify the search path directly by either modifying the system environment variable <code>PYTHONPATH</code> or by '''firing an [[Execute DAT]] onStart()''' with the code snippet below.  
}}<!--
-->{{OPSubSection
|opFamily=COMP
    |sectionName=Using an Actor COMP
    |sectionSummary=When creating an Actor COMP there are some important questions to consider:
* '''Will this Actor be in a Bullet or Flex simulation?''' There are many commonalities between Bullet actors and Flex actors, however they do differ in their functionality, meaning that not all parameters overlap. For Bullet specific parameters see the Bullet page of the Actor COMP and for Flex specific parameters see the Flex page of the Actor COMP.
* '''Will the bodies move?''' A moving body's Kinematic State must be dynamic. A static body can "move" by overriding its position, but this is not recommended since clipping can easily occur and and collisions will be incorrect (because the bodies won't have momentum).
* '''What SOPs will be used to create the collision shape?''' Every Actor COMP has a corresponding collision shape that is created from SOPs. The SOPs can be set through the Collision SOPs parameter, or if that parameter is not set, through the display/render flags of SOPs inside the Actor COMP.
* '''What collision shape will be used?''' The SOPs gathered in the previous stage are used to create the collision shape. Each collision shape has their own pros and cons, which are outlined on the [[Bullet Dynamics]] page. The collision shape is what determines how the body will interact with other bodies (ie. collide). The collision shape does not necessarily correspond with what is displayed/rendered. The collision shape can be shown using the Display Collision Shape toggle.
* '''Will the collision shape be concave?''' If the collision shape is concave and static, simply select Concave from the drop-down menu. If the collision shape is to be concave and dynamic then there is an extra step: convex decomposition. The collision shape must be a Compound collision shape (ie. a group of convex collision shapes) where each part of the compound shape is convex, but combined together create a concave shape. Each part of the compound shape is represented using a single SOP. Consider the letter "T" as an example. "T" is concave so it will need to be split into two separate convex parts: the top line and the bottom line. 2 SOPs would be created (one for each line) for the collision shape that when combined together form the full concave "T". If the "T" were static however, it could remain as 1 SOP.
}}<!--
-->{{OPSubSection
|opFamily=COMP
    |sectionName=Why are my bodies not colliding?
    |sectionSummary=To understand why two bodies might not collide it is important to understand that Bullet simulates discretely. Speed, position, constraints, collisions are all calculated on a frame by frame basis, as opposed to continuously. In the case of Bullet, collisions are calculated at the beginning and the end of a frame. What this means is that if a body is moving a large distance every frame it can clip through other bodies, because it's not colliding with it at the beginning or the end of the frame when collision is calculated. In the same vein, if an object is very thin then other bodies will be able to clip through it easier than something with more depth because bodies won't have to move as far in a frame to completely jump over it.


Continuous collision detection (see parameter) helps to fix this by performing collision detection along the movement vector (between start/end of frame) so that collisions happening between the start/end of frame will be caught. This helps significantly with high linear velocity bodies, but not so much high angular velocity bodies.
<syntaxhighlight lang=python>
import sys
mypath = "C:/Python311/Lib/site-packages" # use the correct path to your installation, sometimes in a user folder
if mypath not in sys.path:
sys.path = [mypath] + sys.path
</syntaxhighlight>


A couple other things to consider changing to fix body "leaking":
This script will prepend your custom Python install site-packages folder to your PATH. Prepending will make sure that your custom packages, when being imported, '''will have priority over any other package with a matching package name found''' in the path. If the package is not found in the custom path, but a package of the same name is found in the TouchDesigner Python site-packages folder then '''it will fall back on this package'''.
# Manually limit the velocity of bodies, or lower the strength of the forces being applied.
# Add depth to very thin collision surfaces. If you're using a Grid SOP as a collision surface, consider using a Box SOP instead. Or, if you're using a Box SOP as the collision shape to contain other bodies inside, consider making the collision shape out of 6 individual Box SOPs (one for each side of the box) combined together.
}}}}
{{ParameterPage
|opFamily=COMP
|pageName=General
|pageSummary=
|items={{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Initialize Actor
|parName=init
|parType=Pulse
|parReadOnly=
|parOrder=0
|parSummary= Recreates the collision shapes for all the bodies in the Actor COMP. Also resets all velocities and position to their default state. Initialize Actor should be pulsed when any changes are made to the SOPs used for creating the collision shape, or for any changes to the instancing OP. 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Update Collision Shape
|parName=updatecs
|parType=Toggle
|parReadOnly=
|parOrder=1
|parSummary=If enabled the Actor COMP will automatically update collision shapes. This will occur when the "Collision SOPs" or "Collision Shape" parameters are changes or the underlying SOPs used to create the collision shape are changed (ie. when their cook count increases). 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Update Collision Shape
|parName=updatecspulse
|parType=Pulse
|parReadOnly=
|parOrder=2
|parSummary=When clicked this will instantly update the collosion shape.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Active
|parName=active
|parType=Toggle
|parReadOnly=
|parOrder=3
|parSummary=Toggle the actor on/off. If the actor is active, then it will be updated as the simulation progress. However, if it is inactive, then it will be removed from the simulation and no longer collide with any of the other actors/bodies. As a result, it's transform will also no longer be updated.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Kinematic State
|parName=kinstate
|parType=Menu
|parReadOnly=
|parOrder=4
|parSummary=The kinematic state defines the Actor COMPs ability to move from external forces. If an object is dynamic, then it is moveable in the simulation, but if it static then it is not.
|parItems={{ParameterItem
|opFamily=COMP
|parName=kinstate
|itemLabel=Static (Infinite Mass)
|itemName=static
|itemSummary=The bodies in this COMP cannot be moved in the simulation.
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=kinstate
|itemLabel=Dynamic (Finite Mass)
|itemName=dynamic
|itemSummary=The bodies in this COMP can move.
}}
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Collision SOPs
|parName=sops
|parType=OP
|parReadOnly=
|parOrder=5
|parSummary=Specifies SOPs or COMPs to use for the collision shape. If a SOP is referenced, then just that SOP will be used for the collision shape. But if a COMP is selected then all SOPs inside of that (recursive) will be used for the collision shape. If this parameter is left blank, then the SOPs selected will be all SOPs inside the Actor COMP with display and render flags on. 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Collision Shape
|parName=shape
|parType=Menu
|parReadOnly=
|parOrder=6
|parSummary=The type of collision shape to make from the selected SOPs. Collision shapes can be viewed using a guide in the Actor COMP's viewer
|parItems={{ParameterItem
|opFamily=COMP
|parName=shape
|itemLabel=Concave (Static only)
|itemName=concave
|itemSummary=Creates a concave collision shape out of all the SOPs. Should only be used for static Actor COMPs. The SOPs used for creating the concave collisions shape should only have polygons with either 3 or 4 vertices. If this mode is selected for a dynamic Actor COMP then a compound shape will be created instead.
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=shape
|itemLabel=Convex Hull
|itemName=convex
|itemSummary=Creates a convex hull out of all the SOPs. A convex hull is a set of points that encloses all other points (in this case, the points from the SOPs), and the shape created from these points is convex. The points of the convex hull will be points from the original set of points (ie. the ones from the SOPs)
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=shape
|itemLabel=Oriented Bounding Box
|itemName=obb
|itemSummary=Creates a bounding box around the SOPs that is oriented to minimize volume.
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=shape
|itemLabel=Axis-Aligned Bounding Box
|itemName=aabb
|itemSummary=Creates a bounding box around the SOPs that has its axis aligned with XYZ (so it's not rotated).
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=shape
|itemLabel=Bounding Ellipsoid
|itemName=bellipsoid
|itemSummary=Creates a minimum volume bounding ellipsoid around the SOP.
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=shape
|itemLabel=Bounding Sphere
|itemName=bsphere
|itemSummary=creates a minimum volume bounding sphere around the SOPs. The difference between this and bounding ellipsoid is that all radii are the same (XYZ).
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=shape
|itemLabel=Compound
|itemName=compound
|itemSummary=A compound collision shape is a collision shape composed of other collision shapes. If the Actor COMP is static then this has the same result as a concave shape. If the Actor COMP is dynamic then each SOP will be created into its own convex hull, then these will all be subsequently merged together into a single compound collision shape. This mode allows you to create concave collision shapes for dynamic bodies using multiple convex SOPs.
}}
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Ellipsoid Tolerance
|parName=elltol
|parType=Float
|parReadOnly=
|parOrder=7
|parSummary=The tolerance of the minimum volume bounding ellipsoid. In other words, how close to the optimal solution it is. 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Infinite Mass
|parName=infinitemass
|parType=Toggle
|parReadOnly=
|parOrder=8
|parSummary=Give the actor infinite mass. If the object is dynamic this will make it unmovable and static. Toggling infinite mass on or off will not require recreation of the collision shape, unlike changing the Kinematic State parameter. 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Mass
|parName=mass
|parType=Float
|parReadOnly=
|parOrder=9
|parSummary=The mass in kilograms of the actor.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Cue Velocity
|parName=cuevel
|parType=Toggle
|parReadOnly=
|parOrder=10
|parSummary=Holds the linear and angular velocity and values given by linvel and angvel. The object will still collide with any other bodies in the simulation. 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Cue Pulse
|parName=cuevelpulse
|parType=Pulse
|parReadOnly=
|parOrder=11
|parSummary=Pulse the linear and angular velocity to values given by linvel and angvel. This will set the velocity to the given value at the beginning of the next frame.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Linear Velocity
|parName=linvel
|parType=XYZ
|parReadOnly=
|parOrder=12
|parSummary=The initial linear velocity of the actor in m/s. This parameter can also be used to modify an actor's linear velocity during a simulation. Additionally, it is used in conjunction with the "Cue Velocity" and "Cue Velocity Pulse" parameters.
|parItems={{ParameterItem
|opFamily=COMP
|parName=linvel
|itemLabel=Linear Velocity
|itemName=linvelx
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=linvel
|itemLabel=Linear Velocity
|itemName=linvely
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=linvel
|itemLabel=Linear Velocity
|itemName=linvelz
|itemSummary=
}}
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Angular Velocity
|parName=angvel
|parType=XYZ
|parReadOnly=
|parOrder=13
|parSummary=The initial angular velocity of the actor in degrees per second in m/s. This parameter can also be used to modify the actor's angular velocity during a simulation. Additionally, it is used in conjunction with the "Cue Velocity" and "Cue Velocity Pulse" parameters.
|parItems={{ParameterItem
|opFamily=COMP
|parName=angvel
|itemLabel=Angular Velocity
|itemName=angvelx
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=angvel
|itemLabel=Angular Velocity
|itemName=angvely
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=angvel
|itemLabel=Angular Velocity
|itemName=angvelz
|itemSummary=
}}
}}
}}
{{ParameterPage
|opFamily=COMP
|pageName=Bullet
|pageSummary=
|items={{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Forces
|parName=forces
|parType=OBJ
|parReadOnly=
|parOrder=0
|parSummary=A list of local forces, meaning forces (ie. Force COMPs) that will only be applied to this actor. 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Use Global Gravity
|parName=globalgrav
|parType=Toggle
|parReadOnly=
|parOrder=1
|parSummary=Toggle for whether to use the Bullet Solver COMP's gravity (global), or its own local gravity. 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Gravitational Acceleration
|parName=gravity
|parType=XYZ
|parReadOnly=
|parOrder=2
|parSummary=Actor's local gravity in m/s^2. Will only be applied if the actor is not using the Bullet Solver COMP's global gravity ie. the "Use Global Gravity" parameter above is turned off.
|parItems={{ParameterItem
|opFamily=COMP
|parName=gravity
|itemLabel=Gravitational Acceleration
|itemName=gravityx
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=gravity
|itemLabel=Gravitational Acceleration
|itemName=gravityy
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=gravity
|itemLabel=Gravitational Acceleration
|itemName=gravityz
|itemSummary=
}}
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Friction
|parName=friction
|parType=Float
|parReadOnly=
|parOrder=3
|parSummary=The kinetic friction of the actor. It is the resistance between two bodies rubbing/sliding. The overall friction is the product of the two bodies touching. For example, if one body has 0 friction and the other has 1, then the overall friction between the two bodies is 0.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Rolling Friction
|parName=rollfric
|parType=Float
|parReadOnly=
|parOrder=4
|parSummary=The rolling friction of the actor. It is the resistance/drag of one body (such as a sphere or cone) rolling on another.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Restitution
|parName=rest
|parType=Float
|parReadOnly=
|parOrder=5
|parSummary=The coefficient of restitution of the actor. The coefficient of restitution is the ratio of the final to initial relative between two bodies/actors when they collide. In other words, restitution is the fraction of kinetic energy preserved after a collision. If two objects collide with 100% (ie. 1) restitution, then, both bodies will bounce off each other at the same speed at which they collided.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Continuous Collision Detection
|parName=ccd
|parType=Toggle
|parReadOnly=
|parOrder=6
|parSummary=Toggles continuous collision detection on/off for this actor. Typically, collision detection is done discretely, meaning that collision is verified at the beginning/end of a frame. However, if a body is going too fast it will move too far in a single frame and therefore clip through any surfaces (ie. No collision detected). Continuous collision detection improves upon this by performing collision detection at intervals between the body's initial and final positions within a frame. Continuous collision detection can affect performance, so even if the parameter is toggled on it will not be used all the time. It will only be used for bodies moving above a velocity threshold. 
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Display Guide
|parName=dispguide
|parType=Toggle
|parReadOnly=
|parOrder=7
|parSummary=Toggles on the display for the collision shape in the COMP viewer.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Center of Mass
|parName=com
|parType=XYZ
|parReadOnly=
|parOrder=8
|parSummary=Specifies the center of mass of the collision shape. The center of mass is the point around which the body will rotate. Center of mass can be viewed using a guide in the Actor COMP's viewer. It is shown as a red axis.
|parItems={{ParameterItem
|opFamily=COMP
|parName=com
|itemLabel=Center of Mass
|itemName=comx
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=com
|itemLabel=Center of Mass
|itemName=comy
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=com
|itemLabel=Center of Mass
|itemName=comz
|itemSummary=
}}
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Feedback CHOP
|parName=feedback
|parType=CHOP
|parReadOnly=
|parOrder=9
|parSummary=A reference to a CHOP from which to feedback. The Actor COMP will read transformation and velocity data (in the correct format, see Bullet Solver CHOP for more information) from the CHOP, and overwrite the current values at the beginning of the next frame. A feedback loop can be created with this parameter and the Bullet Solver CHOP. See Bullet Solver CHOP. NOTE: scale cannot be feedbacked. force[xyz] and torque[xyz] can be used to apply forces to specific bodies.
|parItems=
}}
}}
{{ParameterPage
|opFamily=COMP
|pageName=Flex
|pageSummary=
|items={{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Flex Type
|parName=flextype
|parType=Menu
|parReadOnly=
|parOrder=0
|parSummary=The type of dynamic Flex actor.
|parItems={{ParameterItem
|opFamily=COMP
|parName=flextype
|itemLabel=Fluid
|itemName=fluid
|itemSummary=A fluid actor. The number of particles will be determined by the instance input count.
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=flextype
|itemLabel=Fluid Emitter
|itemName=fluidemit
|itemSummary=A fluid emitter actor. The number of particles will increase at a rate proportional to emission size and speed. Once the maximum is reached particles will be recycled from existing particles.
}}
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Enable Emission
|parName=emit
|parType=Toggle
|parReadOnly=
|parOrder=1
|parSummary=When enabled, the Actor COMP will actively emit particles.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Emission Size
|parName=emitsize
|parType=XY
|parReadOnly=
|parOrder=2
|parSummary=The size of the 2D emission grid. The size represents the number of particles on each side of the emission grid. For example, a 2x5 emission size will emit a grid 2 particles wide and 5 particles high.
|parItems={{ParameterItem
|opFamily=COMP
|parName=emitsize
|itemLabel=Emission Size
|itemName=emitsizex
|itemSummary=
}}<!--
-->{{ParameterItem
|opFamily=COMP
|parName=emitsize
|itemLabel=Emission Size
|itemName=emitsizey
|itemSummary=
}}
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Emission Speed
|parName=emitspeed
|parType=Float
|parReadOnly=
|parOrder=3
|parSummary=The speed the particles come out of the emitter.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Max Emission Particles
|parName=emitmax
|parType=Float
|parReadOnly=
|parOrder=4
|parSummary=Sets the maximum number of particles in the Actor COMP. Once this number is reached, emission will be done by recycling existing particles in the Actor COMP.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Position Feedback TOP
|parName=flexposfb
|parType=TOP
|parReadOnly=
|parOrder=4
|parSummary=A reference to a TOP to feedback position. The TOP should be encoded with the position data that will be used to override position in the simulation. The texture data will be read to correspond with the Flex TOP's position texture.
|parItems=
}}
{{Parameter
|opFamily=COMP
|opType=actorCOMP
|parLabel=Velocity Feedback TOP
|parName=flexvelfb
|parType=TOP
|parReadOnly=
|parOrder=4
|parSummary=A reference to a TOP to feedback velocity. The TOP should be encoded with the velocity data that will be used to override velocity in the simulation. The texture data will be read to correspond with the Flex TOP's velocity texture.
|parItems=
}}
}}{{:COMP Xform Page}}
{{:COMP Pre-Xform Page}}
{{:COMP Instance Page}}
{{:COMP Instance 2 Page}}
{{:COMP Instance 3 Page}}
{{:COMP Render Page}}
{{:COMP Extensions Page}}
{{:COMP Geometry Common Page}}


{{InfoCHOPChannels
Users can also import packages from Python installations that weren't installed with the official Python installer but with alternative Python package and environment managers, [https://derivative.ca/community-post/tutorial/anaconda-managing-python-environments-and-3rd-party-libraries-touchdesigner such as Anaconda].
|opFamily=COMP
 
|opLabel=Actor
Examples of other useful Python modules are [http://wiki.python.org/moin/UsefulModules here].
|infoChannels={{InfoChannel
Unofficial precompiled modules found on Christoph Gohlke's [http://www.lfd.uci.edu/~gohlke/pythonlibs/?q=cp33 website].
|chanName=num_bodies
 
|chanSummary=}}{{InfoChannel
==== MacOS ====
|chanName=num_active_bodies
 
|chanSummary=}}}}
On MacOS, use [https://brew.sh/ Homebrew] to manage your Python installations. Follow the instructions on Homebrew's website to get started.
{{History
 
}}
When Homebrew is installed, you can use the command <syntaxhighlight lang="bash" inline=true>brew install python@3.11</syntaxhighlight> to install Python on your system. The <syntaxhighlight lang=python inline=true>@3.11</syntaxhighlight> after <syntaxhighlight lang="bash" inline=true>python</syntaxhighlight> sets the version, which must be the same as TouchDesigner's.
{{NavBox
 
|Category=COMPs
===== Intel Macs =====
}}
 
{{#invoke:Category|list|COMPs}}
On Intel's Macs, your default Homebrew path should be <syntaxhighlight inline=true>/usr/local/bin/brew</syntaxhighlight>
 
===== ARM Macs =====
 
On ARM's Macs, your Homebrew path should be <syntaxhighlight inline=true>/opt/homebrew/bin/brew</syntaxhighlight>, '''for the native ARM homebrew'''. That is, when using the default Homebrew install command.
 
'''NOTE:''' In some cases, you might want to run Homebrew Rosetta. It is required if you are using the non-native / Intel TouchDesigner build and require a Python version that is not available as an ARM installer on MacOS.
 
To install Homebrew Rosetta, use the following command: <syntaxhighlight inline=true>arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"</syntaxhighlight>.
Your Homebrew Rosetta path should be <syntaxhighlight inline=true>/usr/local/bin/brew</syntaxhighlight>.
 
If you have both Homebrew versions installed on your system, it is advised to add an alias for the Homebrew Rosetta installation.
Use the following command in your terminal <syntaxhighlight inline=true>alias ibrew="arch -x86_64 /usr/local/bin/brew"</syntaxhighlight> where <syntaxhighlight inline=true>ibrew</syntaxhighlight> stands for Intel Brew.
You can add this alias to your terminal profile so that it is persistent.
 
You can now use either <syntaxhighlight inline=true>brew install YOUR_APP_NAME</syntaxhighlight> or <syntaxhighlight inline=true>ibrew install YOUR_APP_NAME</syntaxhighlight> to install ARM or Intel formulas or casks respectively.
 
Continue with your python installation, matching TouchDesigner's Python, as described at the top of this MacOS section. Remember, if you followed the previous steps: when your are using the ARM native TouchDesigner build, use <syntaxhighlight inline=true>brew</syntaxhighlight>, if it's the Intel build running with Rosetta, use <syntaxhighlight inline=true>ibrew</syntaxhighlight>.
 
It can also be useful to add extra aliases, and precede them with an <syntaxhighlight inline=true>i</syntaxhighlight> when they are related to Intel / Rosetta, for Python itself, and pip:
<syntaxhighlight>
alias iPY311=/usr/local/opt/python@3.11/bin/python3
alias iPIP311=/usr/local/opt/python@3.11/bin/pip3
</syntaxhighlight>
 
Now, all you have to do is install your custom (Intel) Python 3.11 packages using <syntaxhighlight inline=true>iPIP311 install YOUR_PACKAGE_NAME</syntaxhighlight>.
 
Once the module is successfully installed, you can import it in TouchDesigner following these next steps:
 
Under the Edit->Preferences menu, tick "Add External Python to Search Path". You can add the search path by modifying the Preference labelled "Python 32/64 bit Module Path". Multiple paths are separated by semicolons (<code>;</code>). You can enter the path to your Python packages (usually <code><python install>/Lib/site-packages</code>)
 
If the preferences method doesn't work for you, there are a couple other methods: you can modify the Python search path directly by either modifying the '''system environment variable <code>PYTHONPATH</code>''' or by '''setting up an [[Execute DAT]] onStart()''' with the code snippet below.
 
<syntaxhighlight lang=python>
import sys
mypath = "/usr/local/lib/python3.11/site-packages" # TIP: This path is printed out in the terminal when installing this Python version with Homebrew
if mypath not in sys.path:
sys.path = [mypath] + sys.path
</syntaxhighlight>
 
This script will prepend your custom Python install site-packages folder to your PATH. Prepending will make sure that your custom packages, when being imported, '''will have priority over any other package with a matching package name found''' in the path. If the package is not found in the custom path, but a package of the same name is found in the TouchDesigner Python site-packages folder then '''it will fall back on this package'''.
 
==== I am getting the following ImportError, what should I do ? ImportError: DLL load failed while importing […] ====
For most cases, it is better to document your environment and to share the project and steps to reproduced with the Derivative team at forum.derivative.ca
 
If you feel adventurous, what is likely to happen is that there is a dependency conflict causing an issue between TouchDesigner and the Python library you are attempting to use.
 
You can use a tool such as [https://github.com/lucasg/Dependencies Dependencies] to get an idea of which libraries your package is depending on. You drag n drop your python package binary, pyd, to the tool and you can see what are the libraries it is depending on. Then you investigate further to find what library might already be used by TouchDesigner, going through the dependencies of dependencies. Tedious.
 
== Python Gotchas ==
There are a few things in standard Python that can trip you up in TouchDesigner. If you find anything that's not included here, post in the forum!
* Some TouchDesigner objects (especially parameters and CHOP channels) will try to act as the correct data type for their context. For example, a Float parameter object (<code>myOp.par.Float1</code>) will act like a floating point number ''in most cases'', but it is still a parameter object. For example <code>round(myOp.par.Float1)</code> will not work. To get the actual value of a parameter or channel, use its <code>.eval()</code> method. If you think you may be encountering this problem, you can tell the difference by using the <code>repr</code> function. For example <code>repr(myOp.par.Float1)</code> will show that this is a parameter and not a number.
* same goes with operator parameter types.  if a parameter is a path to a CHOP, <code>n.par.Chop</code> usually works, but to be safe, <code>n.par.Chop.eval()</code> always works.
* <code>subprocess.Popen</code> doesn't work with file-like objects. See [https://forum.derivative.ca/t/resolved-td-specific-stdoutcatcher-object-has-no-attribute-fileno/140106 this forum post] for details.
* Python threads don't have access to TouchDesigner objects. Search "threading" in the forum to see some workarounds.
 
== More In The Python Category ==

Latest revision as of 17:16, 24 January 2024

Python In TouchDesigner[edit]

TouchDesigner uses Python for scripting tasks. A custom Python build is included, with most of the features of a standard Python installation and a huge number of tools and utilities specific to working in the software.

In addition, selecting Help -> Python Examples in the TouchDesigner UI takes you to the PythonExamples.toe file with 100+ working examples.

Learning Python[edit]

If you don't know Python, here are some good resources for learning:

Python Classes and Modules Available in TouchDesigner[edit]

TouchDesigner includes all the modules in a standard Python installation plus the following:

td: TouchDesigner's Main Python Module[edit]

All td module members and methods are available in scripts, expressions, and the textport. There is no need to import the module or its members explicitly. This is especially important in expressions, which don't allow import statements.

The following can be found in the td module:

  • Main TouchDesigner utilities - the most basic starting points for interacting with TouchDesigner, such as me and op().
  • TouchDesigner Python helper classes - important helper objects used to organize functions and information pertaining to a specific part of TouchDesigner.
  • Operator related classes - every Operator in TouchDesigner has an associated Python class in the td module. Their wiki pages can be accessed by clicking on the Python Help button in their parameter dialog. There are also a number of associated Python objects that are used when working with Operators.
  • Useful standard Python modules - the td module also automatically imports a number of helpful standard modules (e.g. math), allowing them to be accessed in expressions through their namespace.

TouchDesigner Utility Modules[edit]

TouchDesigner also contains utility modules for advanced Python programming. Utility modules are not imported into the td module automatically. Instructions for their use can be found on their wiki pages.

3rd Party Packages[edit]

TouchDesigner includes a number of 3rd party Python packages that are generally useful when working with the software. These are not included in the td module so must be imported explicitly.

Installing Custom Python Packages[edit]

Part of the great power of Python is its access to the countless number of modules that have been created. If you want to use modules that are not included in the above, use the following steps:

Note: When adding your own version for a package that is already shipped with TouchDesigner, you might encounter unexpected behaviors. Many of our internal tools and palette components rely on NumPy and/or OpenCV. Loading different versions of Numpy and/or OpenCV is at your own risk. Some other issue could be with the following: considering a Package A with a dependency B, if updating your sys.path cause a different version of dependency B to load first, it could cause issues with Package A.

Windows[edit]

  1. Install a parallel copy of the same version of Python to the hard disk. The current version of Python shipped with TouchDesigner is 3.11. It can be found here. Use the most recent subversion of 3.11.
    1. Alternatively, you can use a Python package and environment manager, such as Anaconda.
  2. Install the package to the parallel python installation, following its normal installation procedure.
  3. Launch Python and import the module manually to make sure there are no errors outside of the TouchDesigner context.

Once the module is successfully installed, you can import it in TouchDesigner following those next steps:

Under the Edit->Preferences menu, tick "Add External Python to Search Path". You can add the search path by modifying the Preference labelled "Python 32/64 bit Module Path". Multiple paths are separated by semicolons (;).

Finally you can modify the search path directly by either modifying the system environment variable PYTHONPATH or by firing an Execute DAT onStart() with the code snippet below.

import sys
mypath = "C:/Python311/Lib/site-packages" # use the correct path to your installation, sometimes in a user folder
if mypath not in sys.path:
	sys.path = [mypath] + sys.path

This script will prepend your custom Python install site-packages folder to your PATH. Prepending will make sure that your custom packages, when being imported, will have priority over any other package with a matching package name found in the path. If the package is not found in the custom path, but a package of the same name is found in the TouchDesigner Python site-packages folder then it will fall back on this package.

Users can also import packages from Python installations that weren't installed with the official Python installer but with alternative Python package and environment managers, such as Anaconda.

Examples of other useful Python modules are here. Unofficial precompiled modules found on Christoph Gohlke's website.

MacOS[edit]

On MacOS, use Homebrew to manage your Python installations. Follow the instructions on Homebrew's website to get started.

When Homebrew is installed, you can use the command brew install python@3.11 to install Python on your system. The @3.11 after python sets the version, which must be the same as TouchDesigner's.

Intel Macs[edit]

On Intel's Macs, your default Homebrew path should be /usr/local/bin/brew

ARM Macs[edit]

On ARM's Macs, your Homebrew path should be /opt/homebrew/bin/brew, for the native ARM homebrew. That is, when using the default Homebrew install command.

NOTE: In some cases, you might want to run Homebrew Rosetta. It is required if you are using the non-native / Intel TouchDesigner build and require a Python version that is not available as an ARM installer on MacOS.

To install Homebrew Rosetta, use the following command: arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)". Your Homebrew Rosetta path should be /usr/local/bin/brew.

If you have both Homebrew versions installed on your system, it is advised to add an alias for the Homebrew Rosetta installation. Use the following command in your terminal alias ibrew="arch -x86_64 /usr/local/bin/brew" where ibrew stands for Intel Brew. You can add this alias to your terminal profile so that it is persistent.

You can now use either brew install YOUR_APP_NAME or ibrew install YOUR_APP_NAME to install ARM or Intel formulas or casks respectively.

Continue with your python installation, matching TouchDesigner's Python, as described at the top of this MacOS section. Remember, if you followed the previous steps: when your are using the ARM native TouchDesigner build, use brew, if it's the Intel build running with Rosetta, use ibrew.

It can also be useful to add extra aliases, and precede them with an i when they are related to Intel / Rosetta, for Python itself, and pip:

alias iPY311=/usr/local/opt/python@3.11/bin/python3
alias iPIP311=/usr/local/opt/python@3.11/bin/pip3

Now, all you have to do is install your custom (Intel) Python 3.11 packages using iPIP311 install YOUR_PACKAGE_NAME.

Once the module is successfully installed, you can import it in TouchDesigner following these next steps:

Under the Edit->Preferences menu, tick "Add External Python to Search Path". You can add the search path by modifying the Preference labelled "Python 32/64 bit Module Path". Multiple paths are separated by semicolons (;). You can enter the path to your Python packages (usually <python install>/Lib/site-packages)

If the preferences method doesn't work for you, there are a couple other methods: you can modify the Python search path directly by either modifying the system environment variable PYTHONPATH or by setting up an Execute DAT onStart() with the code snippet below.

import sys
mypath = "/usr/local/lib/python3.11/site-packages" # TIP: This path is printed out in the terminal when installing this Python version with Homebrew
if mypath not in sys.path:
	sys.path = [mypath] + sys.path

This script will prepend your custom Python install site-packages folder to your PATH. Prepending will make sure that your custom packages, when being imported, will have priority over any other package with a matching package name found in the path. If the package is not found in the custom path, but a package of the same name is found in the TouchDesigner Python site-packages folder then it will fall back on this package.

I am getting the following ImportError, what should I do ? ImportError: DLL load failed while importing […][edit]

For most cases, it is better to document your environment and to share the project and steps to reproduced with the Derivative team at forum.derivative.ca

If you feel adventurous, what is likely to happen is that there is a dependency conflict causing an issue between TouchDesigner and the Python library you are attempting to use.

You can use a tool such as Dependencies to get an idea of which libraries your package is depending on. You drag n drop your python package binary, pyd, to the tool and you can see what are the libraries it is depending on. Then you investigate further to find what library might already be used by TouchDesigner, going through the dependencies of dependencies. Tedious.

Python Gotchas[edit]

There are a few things in standard Python that can trip you up in TouchDesigner. If you find anything that's not included here, post in the forum!

  • Some TouchDesigner objects (especially parameters and CHOP channels) will try to act as the correct data type for their context. For example, a Float parameter object (myOp.par.Float1) will act like a floating point number in most cases, but it is still a parameter object. For example round(myOp.par.Float1) will not work. To get the actual value of a parameter or channel, use its .eval() method. If you think you may be encountering this problem, you can tell the difference by using the repr function. For example repr(myOp.par.Float1) will show that this is a parameter and not a number.
  • same goes with operator parameter types. if a parameter is a path to a CHOP, n.par.Chop usually works, but to be safe, n.par.Chop.eval() always works.
  • subprocess.Popen doesn't work with file-like objects. See this forum post for details.
  • Python threads don't have access to TouchDesigner objects. Search "threading" in the forum to see some workarounds.

More In The Python Category[edit]