Week 5: Learning about SceneNode and Scene Hierarchy.

·         Please download and unzip the Week5.zip file in the File/WeeklyExamples folder.

 

 

1.       SceneNode:

a.       Example Structure: Hierarchy Window, Prefabs, and Scripts

                                                               i.      Hierarchy Window,

1.       MainCanvas č SceneNodeControl

a.       SceneNodeControl: design to control SceneNodes (more later)

2.       TheWorld: ThePlane, BaseNode,, LocationTester

a.       ThePlane: world reference plane

b.      BaseNode: A 2-level scene node (more later)

c.       LocationTester: drag around in Editor Window to verify locations

                                                             ii.      Materials and Prefabs,

1.       Assets/Materials: 451Shader/451Material Pair:

a.       451Shader: defines MyXformMat (to be passed down by Unity GameObject)

2.       Assets/Resources: Prefabs

a.       UI/SceneNodeControl.prefab: designed to control a SceneNode

                                                          iii.      Scripts: Under Source

1.       Model/TheWorld: has a reference to TheRood (of the scene node)

2.       Model/SceneNode: defines the scene node (more later)

3.       Model/NodePrimitive: all primities (GameObjects) in SceneNode must have this component to load matrix into the corresponding 451Shader

4.       UI_Support/MainController: hangs on MainCanvas not doing anything in this case

b.      The Need: in Parent-Child example, notice that:

                                                               i.      We CANNOT scale the base (cylinder) independent from the tree

1.       E.g., if I want the base to be higher (e.g., y-scale of 5) and not to disturb the tree scale.

                                                             ii.      This suggests we need to have a layer of control that allow us to manipulate the geometry of the base (parent) independently from the child.

                                                            iii.      čNeed a SceneNode class

c.       Solution: separate the functionality of these two (user transformation and primitives needs)

                                                               i.      User transformation need č SceneNode.cs

1.       Collect all elements/primitives that we want user to manipulate as an unit

a.       č A list of all primitives for this node

2.       Provide the interface for the user to manipulate

a.       č A transform the user can manipulate

3.       NodeOrigin position is the “reference” for all primitives in the node

4.       Note the net translation by NodeOrigin in the transformation

                                                             ii.      Primitive: size/rotation/location setting  č NodePrimitive.cs

1.       Simple primitive with transforms

2.       Note respecting Scene Node transform!

3.       Passing computed Xform to the shader

a.       č Only works with shaders that defines MyXformMat and MyColor (e.g., 451Shader)

d.      So, the following are pairs, we need both of the pairs for our hierarchy to work

                                                               i.      Shader-Material pair:

1.       Shader: Remember our 451 shader defines MyXformMat

                                                             ii.      SceneNode and NodePrimitive pair

1.       SceneNode:  must compute composite parent transform

2.       NodePrimitive:  must compute composite transform from SceneNode, AND load MyXformMat + color

                                                            iii.      MyWorld:

1.       Must have root node access and call compute xform!!

e.      UI support: talk about SceneNodeControl is now a prefab. Relatively straightforward

f.        By the way: how to export/import package

g.       Try:

                                                               i.      LocationTester: a sphere to be moved to specific position (e.g., (0, 6, 0)) to verify proper NodeOrigin positions (especially at runtime)

h.      Summary: The three main classes are (all three are in Assets/Source/Model):

                                                               i.      NodePrimitive: For the primitives in a scene node

                                                             ii.      SceneNode: For the scene nodes

                                                            iii.      TheWorld: Note the Update() function!

1.       Recall that we define SceneNode::CompsiteXform() to compute the node hierarch transforms and call all of the NodePrimitives to load the concatenated transform into the shader. Notice:

a.       We do not perform this operation in the Update() function because we need control over the order of scene node’s invocation: parents’ first followed by children, and then grandchildren, etc. Unity calls update in some order that is unclear to us, that’s why we cannot depend on Unity.

b.      We must invoke the root’s CompositeXform() at each re-draw cycle.

c.       This is performed in TheWorld::Update(). Take a look, we simply must keep a reference to the root of the scene hierarchy in the world, and invoke the CompositeXform() at each update.

                                                           iv.      This image depicts the BaseNode 2-level Hierarchy.

i.         When building your own hierarchy, remember this! You MUST set up TheWorld::TheRoot connection, otherwise, nothing will show! J.

 

2.       Exercise working with SceneNode

a.       Fun Shader: 451ShaderWithTexture

                                                               i.      Same as 451Shader created as an Unlit Shader

                                                             ii.      Did not remove _all_ stuff, left “Texture” stuff around

                                                            iii.      Also defined MyColor to be composited to the final color

b.      Fun Material: 41MaterialWithTexture: material defined based with 451ShaderWithTexture

                                                               i.      Notice, the material allows the “dropping in” of a texture (image file!)!!

c.       Exercise: one level scene node of a tree (OneLevelSN)

                                                               i.      A tree with NodePrimitive Component: DOES NOT WORK

1.       Notice, a tree with NodePrimitive behavior does not work (need to be in a scene node)

                                                             ii.      A empty GameObject with SceneNode behavior (name this OneLeveSN)

1.       Tree must be a child

2.       Need to connect NodePrimitive (the tree) with the SceneNode

3.       Still does not work!?

                                                            iii.      TheWorld: must have reference to the root (empty game object)

1.       Check out TheWorld again, initialize the loading of all transformations!!

                                                           iv.      Try:

1.       Set LocationTester to (0, 5, 0)

2.       Set the OneLevelSN (GameObject) to location (0, 0, 0) with NodeOrigin of (0, 5, 0)

3.       Now rotate the scene node and explain what is going on!

a.       SceneNode NodeOrigin offset affects all primitives in the node!

b.      Since NodeOrigin is at (0, 5, 0), and Tree with translation of (0, 0,0) from the scene node, the tree should locate at the NodeOrigin of the Scene node

                                                                                                                                       i.      Thus, Tree is located at (0, 5, 0)

c.       Now, when rotate the scene node, since NodeOrigin is (0, 5, 0), the Tree rotates as though the center is located at is bottom center.

4.       Why is this interesting?

d.      Exercise: two levels of scene notes (TwoLevelSN)

                                                               i.      How can we create a scene hierarchy with two levels of the fun trees one stack on top of the other?

e.      Exercise: Two levels with two siblings side by side? (TwoLevel2SN)

                                                               i.      Can we have two second generation sibling side-by-side?

f.        Can you now, build a 3-level hierarchy? And more?

 

3.       PointOnHierarchy: Object positions in the world

a.       Drag LocationTester to the top-tip of a Tree at default position to see that tip is located at: (0.19, 12.69, 3.88)

b.      Now, with OneLevelSN, I want to keep the AxisFrame sticking at the tree top-tip

                                                               i.      Last line in SceneNode.cs!

1.       Need to consider the scene node’s NodeOrigin offset

                                                             ii.      Only need to figure the initial position, one simple transform call!!

4.       Transform Local vs World:

a.       With all the matrix studied, now let’s examine the difference between

                                                               i.      Transform.localPosition and Transform.position

b.      Scene:

                                                               i.      Parent/Child Square

                                                             ii.      AxisFrame: this is the origin

                                                            iii.      TransformLocal with black sphere

                                                           iv.      TransformWorld with white sphere

c.       Script: AnalyzeXform.cs

                                                               i.      LocalTransform: connected to TransformLocal (Black)

                                                             ii.      WorldTransform: connected to TransformWorld (white)

                                                            iii.      Script on ChildSquare

d.      Interaction and observe: in the editor

                                                               i.      Run to observe

1.       the TransformLocal is at the world origin small insize

2.       the TransformWorld is at the actual ChildSquare transform values in the Inspector

                                                             ii.      Manipulate the parent/child objects observes

1.       TransformWorld always “stick” to ChildSquare

2.       TransformLocal accurately reflect the values in ChildSquare transform in the inspector

                                                            iii.      Notice: the local/global button at the top of the UI

When local: refer to the ChildSquare coordinate (Y is pointing down)

When Global: refer to the world (Y is pointing up)

e.      Learned:

                                                               i.      Seems like transform.position: is the concatenation with parent transform?! J

                                                             ii.      We ALWAYS use local, because we want to get values that are actually in the inspector!

                                                            iii.      FACT: if we have a flat hierarchy (no parent-child relations), it really DOES NOT matter if we access transform.position or transform.localPosition.

 

5.       Decomposing TRS: how can we verify transform.position is the result from the parent?

a.       Scene and script: identical to above, only change, a few lines in AnalyzeXform.cs

b.      AnalyzeXform.cs::update()

                                                               i.      Note, the two mode to compute world position of the child

                                                             ii.      We concatenate our own TRS with parent’s TRS

                                                            iii.      And then, we decompose the result back into separate T R and S transform components! J

c.       Note:

                                                               i.      Translation is column-3 (we already know this)

                                                             ii.      Scale: in x/y/z, is the size of the vectors in Column 0, 1, 2

1.       We did not know this

                                                            iii.      Rotate: this is the most interesting, we can define a rotation in 3D by specifying

1.       Construct a rotation from rotating “FromTo”

2.       Construct a rotation from rotating a Pair of Vectors!?

3.       What is the difference?

                                                           iv.      This “simple decomposition” works ONLY for matrices concatenated based on TRS

d.      Learned:

                                                               i.      The difference between transform.position and transform.localPosition (consider ancestor transform vs simply looking at the numbers showing in the Inspector)

                                                             ii.      In most graphical applications, where transformations are almost always described based on TRS, we can decompose a transformation matrix into TRS components.

                                                            iii.      Rotation defined based on two vectors (instead of one single vector) gives a definitive and well-define answer

e.      Hint: MP4 the axis frames of selected SceneNode, you need to understand this!