SceneHook and DisplayControl
-
On 26/02/2018 at 23:06, xxxxxxxx wrote:
User Information:
Cinema 4D Version: r19
Platform: Mac OSX ;
Language(s) : C++ ;---------
Hi,i've got a project, the main idea is to draw the object wireframe in a selected color. (based on the object color or the layer color or an arbitrary color)
I've decided to rebuild something like the layermanager. So i got a sceneHook to store a list of dummy nodes with colors. When i drag object on those "mylayer" i'm adding in the object's BaseContainer a baselink to the layer. (not sure if it's something i'll go with)
In the scenehook, i'm using inside the function DisplayControl the function
bd->DrawPolygonObject(bh, op, DRAWOBJECT_FORCELINES|DRAWOBJECT_USE_CUSTOM_COLOR,nullptr,mycolor);
And it's working fast.
The problem is when i'm trying to access the object base container and retrieve the color of my "mylayer"
the function "DisplayControl" is executed twice, the first "pass" i'm only getting an empty basecontainer with this codeconst BaseContainer* bcNode = op->GetDataInstance();
that's the same if i'm asking for the name's object or anything else but the mesh informations (pointscount, polycount) (asking for the first tag doesn't work neither)
The second time "DisplayControl" is executed, i can get my color but the "DrawPolygonObject" return DRAWRESULT_SKIP.
i've tried to use the "Draw" functions with some draw lines but my code is so slow ^^'
i don't know where to look. I'm pretty sure you'll have some tips.
i hope my description is clear enoughcheers
Manu. -
On 27/02/2018 at 01:46, xxxxxxxx wrote:
Hello,
DisplayControl() is not used to draw arbitrary shapes in the viewport. DisplayControl() should be implemented to fill the given ControlDisplayStruct structure. See the documentation of SceneHookData::DisplayControl().
DisplayControl() is not called for different "passes". DisplayControl() is called for each selected object in the scene. The filled ControlDisplayStruct defines how this object should be displayed in the viewport.
To draw arbitrary shapes one must do that in the Draw() function.
If you are still interested in using DisplayControl() here is an example on how it is used:
class VertexColorSceneHook : public SceneHookData { INSTANCEOF(VertexColorSceneHook, SceneHookData); public: // This SceneHook example defines polygon vertex colors for each selected polygon object. // These colors are used to display the objects in the viewport. Bool InitDisplayControl(BaseSceneHook* node, BaseDocument* doc, BaseDraw* bd, const AtomArray* active) { if (active && active->GetCount() > 0) return true; return false; } Bool DisplayControl(BaseDocument* doc, BaseObject* op, BaseObject* chainstart, BaseDraw* bd, BaseDrawHelp* bh, ControlDisplayStruct& cds) { // handle only polygon objects if (!op || !op->IsInstanceOf(Opolygon)) return true; // check if the object is selected or if the cache parent is selected Bool active = op->GetBit(BIT_ACTIVE); if (!active) { if (op->GetCacheParent() && op->GetCacheParent()->GetBit(BIT_ACTIVE)) active = true; } // if the object is not selected, don't handle it if (!active) return true; // create colors for each polygon PolygonObject* poly = static_cast<PolygonObject*>(op); const Int32 polyCount = poly->GetPolygonCount(); if (polyCount > 0) { const Float stepSize = 1 / Float(polyCount); Float hue = 0.0; Vector32* _colors = NewMem(Vector32, 4 * polyCount); if (_colors == nullptr) return false; // fill with colors Int32 colorIndex = 0; for (Int32 i = 0; i < polyCount; ++i) { // make color const Vector hsv = Vector(hue, 1.0, 1.0); const Vector32 rgb = (Vector32)HSVToRGB(hsv); hue += stepSize; for (Int32 p = 0; p < 4; ++p) { _colors[colorIndex] = (Vector32)bd->ConvertColor((Vector)rgb); colorIndex++; } } // set ControlDisplayStruct cds.vertex_color = _colors; cds.perPolygonVertexColor = true; return true; } return true; } void FreeDisplayControl() { } //------------------------------------------ static NodeData* Alloc() { return NewObj(VertexColorSceneHook); }; };
-
On 27/02/2018 at 02:38, xxxxxxxx wrote:
Thanks for the exemple.
So i don't understand why i see DisplayControl called twice the number of object. (even if they are not selected)
My problem is more about drawing wireframe of objects (selected or not) without slowing down the viewport.
-
On 27/02/2018 at 06:06, xxxxxxxx wrote:
ok i was not editing the object, only working with primitive
now it's almost working as expected but it's really slow.
Cinema4D's wireframe mode over shading is not slow like that.talking about DisplayControl, i didn't understood the purpose of the chainstart parameter.
-
On 27/02/2018 at 09:20, xxxxxxxx wrote:
Hello,
I was mistaken, DisplayControl() is called for all objects in the scene (the limitation to active object only applies to above example). If is called for "real" object as well as objects in caches. So for a "Cube" generator it is called for the generator as well as the polygon object in its cache. The chainstart argument references the parent object of such a cached object.
A way to draw a wireframe of an object is to use the corresponding display options of BaseDrawHelp. You find an example in the BaseDraw Manual.
best wishes,
Sebastian -
On 27/02/2018 at 23:45, xxxxxxxx wrote:
The information about chainstart was like switching on the light.
I just have to check the chainstart to get my information from either op or chainstart.
in every case i can callbd->DrawPolygonObject(bh, op, DRAWOBJECT_FORCELINES| DRAWOBJECT_USE_CUSTOM_COLOR, nullptr, color);
That's why this functions return DRAWRESULT_SKIP when it's called for the "cache". This make sense now.
I know i should use the draw function but this way i don't have to walk through the hierarchy.
thanks a lot for the help ;D