HDK
|
DOPs is a data-driven processing paradigm. The simulation consists of any number of DOP Objects. Each DOP Object has a unique ID and non-unique name. DOP Objects in the simulation are instances of SIM_Object.
The meaning and behavior of a SIM_Object is defined by what data is attached to it. Attached data (instances of SIM_Data) have two properties: type and name. The name isn't stored with the data itself, since the same data may belong to multiple objects and be referred to by different names, but is instead stored with the owner of the data. Since SIM_Data can contain SIM_Data, this owner can be a SIM_Object or SIM_Data.
In addition to SIM_Object and SIM_Data there is a third kind of data, the SIM_Relationship. Relationships store properties that apply to groups of SIM_Objects. Each relationship has two groups of SIM_Objects it refers to, the affector and affectee. This defines, in the case of, for example, collision relationships, which way the coupling should occur. Relationships can also have data attached to them in the form of SIM_Data to further describe the meaning of the pairing. This is used in constraint relationships, for example, to store the type of constraint that applies to the pair.
DOP processing is best understood of consisting of two passes.
The first pass is the network processing. This pass occurs at the DOP level of the code and parses the network graph and applies the changes it describes. Expressions and keyframes are evaluated in this pass. The main purpose of this pass is to import information from the rest of Houdini and to dress up objects with the initial values they need to solve for the next timestep.
The second pass is the simulation pass. This processing occurs at the SIM level, so lacks access to channels or expressions. The SIM_Engine will group objects according to their attached data named 'Solver'. The named Solver data should be of data type SIM_Solver. That data's SIM_Solver::solveObjects method is then invoked to perform the simulation. The SIM_Solver::solveObjects method can then create, destroy, or modify any objects, data, or relationships as needed to complete its timestep of simulation.
Each SIM_Object in a DOP Simulation may have a home DOP_Node. This is the node that created that SIM_Object. If it has no home, either because it was created by a solver or loaded from disk from another simulation, it is exempt from the network pass.
In the network pass, SIM_Objects will each go to their home node. There they will process in a top-down fashion the DOP_Nodes they encounter en route to the Display flagged node. While this route is executed in a top down manner, it is discovered in a bottom up manner, this is how switch nodes successfully control which wire will be live, and why switch nodes occur at the end, not the start, of a branch.
The most common operation is the addition or modification of data on the SIM_Objects. This can be done with an Apply Data node or, as a syntactic sugar to clean up the network, most data nodes can be inlined to mean the same thing. When an apply data is performed it will evaluate its secondary inputs to get the data to attach. This evaluation is done in a left to right order, so data on the right will replace and be attached after data to the left.
Because this pass is done before the simulation stage, data that will be created during the solve will not yet be available. The state of the dop simulation, as queried with dopoption expressions will reflect the current, partially evaluated, status of the simulation.
The SIM_Engine collates all the SIM_Object's according to the 'Solver' subdata that is attached to them. SIM_Objects that share the same SIM_Data named 'Solver' are candidates to be solved simultaneously with a single SIM_Solver::solveObjects invocation.
These groups are further split, however, according to the relationship information. The SIM_RelationshipCollide defines groups of SIM_Objects that are to have one-way or two-way coupling performed. Satisfying these requirements may require further subdividing the solve groups so that each group of SIM_Objects has a mutual collision relationship with everything else in that group.
The next decision is to determine the order of processing the simulation objects. Within a mutual relationship group this is left to the SIM_Solver::solveObjects implementation, which in the case of SIM_SingleSolver, defaults to solving in order of object id.
The order between groups is determined by the relationship information. A relationship specifies an affector and affectee group. The rule is for the affectee objects to be solved after the affector objects, thus ensuring the up to date version is available. This is one use of the SIM_RelationshipEmpty to ensure solve orders where it is known that a solver has an implied dependency on another SIM_Object.
Some solvers, such as SIM_SolverMulti or GAS_SubSolver also accept solvers as subdata. In this case they usually operate in the order that the data is attached. This, in the case of data created from the network, is the left to right attachment order.