{"action":"created","issue":{"url":"https://api.github.com/repos/dartsim/dart/issues/394","labels_url":"https://api.github.com/repos/dartsim/dart/issues/394/labels{/name}","comments_url":"https://api.github.com/repos/dartsim/dart/issues/394/comments","events_url":"https://api.github.com/repos/dartsim/dart/issues/394/events","html_url":"https://github.com/dartsim/dart/issues/394","id":80656727,"number":394,"title":"VisualNode & CollisionNode","user":{"login":"mxgrey","id":1307217,"avatar_url":"https://avatars.githubusercontent.com/u/1307217?v=3","gravatar_id":"","url":"https://api.github.com/users/mxgrey","html_url":"https://github.com/mxgrey","followers_url":"https://api.github.com/users/mxgrey/followers","following_url":"https://api.github.com/users/mxgrey/following{/other_user}","gists_url":"https://api.github.com/users/mxgrey/gists{/gist_id}","starred_url":"https://api.github.com/users/mxgrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mxgrey/subscriptions","organizations_url":"https://api.github.com/users/mxgrey/orgs","repos_url":"https://api.github.com/users/mxgrey/repos","events_url":"https://api.github.com/users/mxgrey/events{/privacy}","received_events_url":"https://api.github.com/users/mxgrey/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dartsim/dart/labels/Comp:%20API","name":"Comp: API","color":"fbca04"},{"url":"https://api.github.com/repos/dartsim/dart/labels/Comp:%20Collision","name":"Comp: Collision","color":"fbca04"},{"url":"https://api.github.com/repos/dartsim/dart/labels/Comp:%20Kinematics","name":"Comp: Kinematics","color":"fbca04"},{"url":"https://api.github.com/repos/dartsim/dart/labels/Comp:%20Rendering","name":"Comp: Rendering","color":"fbca04"},{"url":"https://api.github.com/repos/dartsim/dart/labels/Kind:%20Feature","name":"Kind: Feature","color":"009800"},{"url":"https://api.github.com/repos/dartsim/dart/labels/Priority:%20Medium","name":"Priority: Medium","color":"0052cc"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":84,"created_at":"2015-05-25T20:27:18Z","updated_at":"2015-10-27T22:38:24Z","closed_at":null,"body":"I think it would be appropriate to begin a conversation about the VisualNode/CollisionNode concept which is intended to replace the current method of using purely the Shape class to provide visualization and collision information. I don't anticipate this being finished any time before version 5.1, but I think it's worth opening the conversation now to give us some time to share ideas and flesh out a design.\r\n\r\nTo review, the current way Shapes are used is:\r\n(i) The Entity class has a ``std::vector`` of ``std::shared_ptr<Shape>`` which it uses for visualization\r\n(ii) The BodyNode class has a ``std::vector`` of ``std::shared_ptr<Shape>`` which it uses to check collisions\r\n\r\nThe nice thing about this scheme is that it allows us to share shape information between multiple Entities/BodyNodes which saves on memory. The downside is that Shape has several features, such as Shape::setLocalTransform and Shape::setColor, which could result in destructive interference if two Entities are sharing the Shape but want that shape to have a different local transform or a different color.\r\n\r\nAnother issue with the current scheme is it does not allow a single BodyNode to have different parts with different physical properties, like coefficients of friction and restitution. A real physical body will have different friction properties on different parts, and different restitution properties on different parts, but DART cannot currently model that. Making friction and restitution properties part of a CollisionNode and allowing a BodyNode to have multiple CollisionNodes would address this issue.\r\n\r\n### Design suggestions\r\n\r\nI think there is an interest in having the VisualNode and CollisionNode classes inherit the Frame class. This makes sense, because we want these Node classes to have a local transform property, and it would be convenient to have a reference frame tied to the Shapes. However, there is a bit of a conflict here: if we make a VisualNode responsible for visualization and we make VisualNode a Frame, then this means that we might need to remove visualization features from Entities, because classes that are derived directly from Entity (rather than from Frame) are expected to leaf nodes in the kinematic tree, so it would not make sense for a raw Entity to have child VisualNodes (since this would contradict the idea that the Entity is a leaf).\r\n\r\nSo I have two suggestions to offer for how to resolve this:\r\n\r\n(1) **We remove all visualization features from Entity.** This would make the raw Entity class far less valuable, but maybe that's okay. Instead of creating an Entity to render an arbitrary (and non-physical) Shape in a scene, the user would have to create a SimpleFrame (which would inherit VisualNode) and fill it with some Shapes.\r\n\r\n(2) **We put all the visualization API into Entity.** We would also create a VisualNode class that inherits the Frame class, but its API for visualizing shapes will be entirely derived from Entity. This means that everything that inherits Entity will be able to contain its own Shapes, and the visualization of all those Shapes could be manipulated by the user. My main concern here is this could result in confusion: The BodyNode class would be able to contain visualization Shapes, but it would also have VisualNodes that can contain visualization Shapes, so the user might be confused about which to use when trying to manipulate visualizations.\r\n\r\nOf these two options, I think I would prefer (1).\r\n\r\n### Visual vs. Collision Node\r\n\r\nThe purposes of the VisualNode and the CollisionNode would be slightly different: VisualNode would be an interface for manipulating how things get rendered, while CollisionNode would contain some physical property data which describe how collisions should be handled.\r\n\r\n@psigen brought up how this type of separation between visualization and collision can be troublesome, and he requested that the concepts of the two classes be merged into a single ShapeNode class. Indeed, at the core of the two classes there is just a ``std::vector`` of ``std::shared_ptr<Shape>`` and a local transform, but the ShapeNodes being used for visualization would still need to be kept separate from the ShapeNodes being used for collision, because you do not always want to render everything that's used for collision checking, and you don't always want to collision check everything that's used for visualization. So rather than a ShapeNode class that has all the features of both, I would propose just having a way to implicitly convert a VisualNode into a CollisionNode and a CollisionNode into a VisualNode. An implicit conversion should address the main source of inconvenience that arises from keeping visualization and collision data separate."},"comment":{"url":"https://api.github.com/repos/dartsim/dart/issues/comments/151665639","html_url":"https://github.com/dartsim/dart/issues/394#issuecomment-151665639","issue_url":"https://api.github.com/repos/dartsim/dart/issues/394","id":151665639,"user":{"login":"mkoval","id":142251,"avatar_url":"https://avatars.githubusercontent.com/u/142251?v=3","gravatar_id":"","url":"https://api.github.com/users/mkoval","html_url":"https://github.com/mkoval","followers_url":"https://api.github.com/users/mkoval/followers","following_url":"https://api.github.com/users/mkoval/following{/other_user}","gists_url":"https://api.github.com/users/mkoval/gists{/gist_id}","starred_url":"https://api.github.com/users/mkoval/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkoval/subscriptions","organizations_url":"https://api.github.com/users/mkoval/orgs","repos_url":"https://api.github.com/users/mkoval/repos","events_url":"https://api.github.com/users/mkoval/events{/privacy}","received_events_url":"https://api.github.com/users/mkoval/received_events","type":"User","site_admin":false},"created_at":"2015-10-27T22:38:24Z","updated_at":"2015-10-27T22:38:24Z","body":"> All you have to do is have your derived `Addon` type also inherit AddonManager and include its AddonManager::State and AddonManager::Properties as part of its Addon::State and Addon::Properties. But we don't want to assume that an Addon will also be an AddonManager because in most cases we're not going to need or even want that.\r\n\r\nI thought @mklingen was commenting on the fact that the `Skeleton`-`BodyNode`-`Joint` relationships are handled specially. Is that not the case?"}}