Relations: BaseObject,RayObject,OPolygon [SOLVED]
-
On 16/10/2014 at 02:00, xxxxxxxx wrote:
Gosh, sorry for not reading it! Well then I don't really know..
-
On 16/10/2014 at 19:33, xxxxxxxx wrote:
Hi FrozenTarzan,
I can tell you almost have the full picture, but are fuzzy with the various relationships between the class hierarchies and the type values across the various objects. I agree it's a bit confusing, it took me some time to sort it out. Here's what I found:
- PolygonObject is a child class of PointObject, which is a child class of BaseObject. Spheres are instantiated as BaseObjects, and so do not contain any PolygonObject data. This affects the RayObjects in the same way, that is, in terms of not having PolygonObject data when they are of sphere type.
- RayObject is a struct that can be instantiated and does not inherit from anything. Its data members are used or ignored depending on on how its data member called 'type' is set. If it's of type polygon, several of its pointer data members are used to access data needed to represent it. If it's of type sphere, the pointer data members only required for polygons are set to null because they are not needed. That is, for some reason, there are no 'RayBaseObject' / 'RayPolygonObject' classes to mirror the BaseObject / PolygonObject relationship.
In your example:
Cone and Cube are instantiated PolygonObject objects, and Null is an instantiated BaseObject. Therefore, the RayObjects for Cone and Cube are set to the polygon type, and the RayObjects point to PolygonObjects that contain the required data to represent them (polymorphism is used through BaseObject pointers). You happen to be able to use GetUp() and GetCacheParent(), simply because the PolygonObjects exist at all.
As for the Sphere, it is represented as a BaseObject and its RayObject equivalent is set to type sphere, which does not point to any PolygonObjects because it does not need any polygon data, only the RayObject::mp to represent the center of the sphere, and its radius, represented by RayObject::rad.x and RayObject::rad.y. It's not really an "other strange thing", as what is really the 'oddball' RayObject is the polygon type, because it's the only type that needs to point to PolygonObject data, unlike sphere, sky, and floor. It's probably not an optimization, but simply a consequence of polygons requiring more data than the other types.
Therefore, if you absolutely need to retrieve tags, or do anything else that requires your sphere to have PolygonObject data representing it to get the connection, then you most likely have to convert it to a polygon, as you state. Otherwise, there's nothing to make the connection you get with polygon type objects, because the data that creates the connection simply doesn't exist for spheres. Perhaps this clarifies how you have to conceptualize these various objects, and you'll find a different solution that is less 'hacky', as you state.
I hope that helps!
Joey
-
On 17/10/2014 at 04:07, xxxxxxxx wrote:
Hey Joey,
thanks for the clarifications! I will try to implement my "hacky" approach.
My own raytracer also handled spheres in another fashion, because the math to compute a ray/sphere intersection is almost as complicated as to compute a ray/triangle intersection. So to get a smooth sphere one would require a huge amount of polygons/triangles, which is of course a great impact for performance.
Regarding the tangents of polygon objects I found this thread:
https://developers.maxon.net/forum/topic/5229/5224_tangent-vectors-solved&KW=tangent&PID=21392#21392So I will compute them by my own, using this source:
http://www.terathon.com/code/tangent.htmlIf I have problems with cloning the Spheres (BaseObjects) and making them editable, I will report back to you
-
On 17/10/2014 at 04:35, xxxxxxxx wrote:
Hi FrozenTarzan,
I'm doing my own raytracer too , if you need any help in raytracing don't hesitate to ask
-
On 17/10/2014 at 06:14, xxxxxxxx wrote:
Hi FrozenTarzan,
I'm glad that cleared things up for you. I know it means there isn't an easy way out, but you were already on the right track. Sure, let us know if you have any issues, I know turning a sphere into a polygon probably means a lot more data is created than otherwise would have been necessary.
Thanks for replying back,
Joey Gaspe
SDK Support -
On 17/10/2014 at 11:55, xxxxxxxx wrote:
It took me only a few minutes to run into a problem^^
When a user places a sphere into the scene, then this sphere is a parametric one (not editable). This sphere is treated specially, as we discussed earlier and is of type O_SPHERE in the raytracer. So my plan was to ignore it and handle spheres on my own by cloning them and making them editable, so in some sense bake everything so that I can access tags, vertices and so on. This would work, but when the user adds deformers to the spheres, the raytracer (of course) has to use polygons again, and so they disappear as RayObjects of type O_SPHERE and are RayObjects of type O_POLYGON.
Another fantastic image to make it clear
So it's simple: When I disable the deformers, the spheres are O_SPHERE and when I enable them they are O_POLYGON.
This behavior is really understandable, but I must find a way to work around it. Everything would be solved if I could get a link to the original object in the hierarchy. Then I would know that a O_POLYGON was originally a sphere, so I could tell my own algorithm that it should not export the sphere (by cloning, baking,...) because it already was transformed by C4D for me.
Does anyone have an idea to get such link? The link is, as discussed, always nullptr for O_SPHERE RayObjects. I really don't know why. It would be great if a developer could name a reason for this.
-
On 17/10/2014 at 12:59, xxxxxxxx wrote:
I'm not sure where is the problem, but from what you say:
if it has active deformers, then the type will be O_POLYGON, and if it hasn't then the type is O_SPHEREwhat about dynamic casting? if it is O_POLYGON then pass it, if it is O_SPHERE then process it with your own bake methods
-
On 17/10/2014 at 21:17, xxxxxxxx wrote:
Hmm... I don't want to be mean, but from what I wrote in the whole thread, it should be clear, that there is no way to dynamic cast a RayObject to anything else, because there is no inheritance hierarchy.
And as we discussed earlier, it is not possible to get to the polygons of a O_SPHERE, because it has none, so my plan was to export a polygonized version of the Osphere (!) which is a BaseObject, not a RayObject. The problem is that I don't have the link to the original object, so I cannot tell if a O_POLYGON RayObject was a sphere originally, in which case I would not have to do the cloning thing.
-
On 17/10/2014 at 21:19, xxxxxxxx wrote:
Oh, and yes I could check the sphere in the object hierarchy for deformers, but I would have to be sure that this is the one and only thing where C4D transforms a parametric sphere into a polyogonized version automatically. There might be tags or other mechanisms that do the same. So if I cannot guarantee that only deformers do that, my code will not be stable in any circumstances.
-
On 18/10/2014 at 02:57, xxxxxxxx wrote:
well sorry for this , wasn't reading the whole thread, now I understand a little more about how they inherit
about:
"So it's simple: When I disable the deformers, the spheres are O_SPHERE and when I enable them they are O_POLYGON.This behavior is really understandable, but I must find a way to work around it. Everything would be solved if I could get a link to the original object in the hierarchy. Then I would know that a O_POLYGON was originally a sphere, so I could tell my own algorithm that it should not export the sphere (by cloning, baking,...) because it already was transformed by C4D for me."
I sense I don't understand this part, if there is no deformers, then it will be O_SPHERE , where you will handle it by your own methods, now if there is deformers, then it will be O_POLYGON with all of its data ready for you, I can't figure out where is the problem here "may be I'm missing something"
-
On 18/10/2014 at 03:08, xxxxxxxx wrote:
unless you want to process the O_SPHERE as triangles, and from this thread I can see that Cinema 4D won't give you this data
a possible solution, is to compare all O_SPHERE objects with the object hierarchy "spheres" transformation matrix 4x4 + radius, so you can guarantee that they are exactly the same object (but this may fail if you have multiple spheres with the same radius at the same location, where they have different types "e.g. Tetrahedron, ..." but this seems to be a near impossible case)
another solution (which would be much better!!) , is:loop over all spheres on object hierarchy, and turn off "render perfect" , I think this should force them to be O_POLYGON
-
On 19/10/2014 at 12:43, xxxxxxxx wrote:
Regarding the deformers, I posted my thoughts above:
"Oh, and yes I could check the sphere in the object hierarchy for deformers, but I would have to be sure that this is the one and only thing where C4D transforms a parametric sphere into a polyogonized version automatically."The hint about "render perfect" sounds promising. I will try that tomorrow!
-
On 20/10/2014 at 05:38, xxxxxxxx wrote:
Hey Mohamed, thanks a lot, it works!
Here's the code I use now to treat spheres as PolygonObjects. When "render perfect" is turned off, they are all converted to O_POLYGON RayObjects, so the rest of my code works as is
// for each BaseObject in hierarchy: if (pObject->GetType() == Osphere) { BaseContainer* baseContainer = pObject->GetDataInstance(); if (baseContainer != nullptr) { bool renderPerfect = baseContainer->GetBool(PRIM_SPHERE_PERFECT); if (renderPerfect) { GePrint("Parametric sphere found! Turing off \"render perfect\"!"); baseContainer->SetBool(PRIM_SPHERE_PERFECT, false); } } }
Thanks again, this made my day!
-
On 20/10/2014 at 06:02, xxxxxxxx wrote:
glad that it worked , but when do you call this function? "I think I will face the same problem at some point in my render engine, and I need to call the function before Cinema 4D data filling"
-
On 21/10/2014 at 03:14, xxxxxxxx wrote:
I call it in the Execute function of my VideoPostData plugin:
RENDERRESULT MyVideoPostDataPlugin::Execute(BaseVideoPost* node, VideoPostStruct* vps) { if (vps->error == nullptr || *vps->error != RENDERRESULT_OK || vps->thread->TestBreak()) { return RENDERRESULT_OK; } if (vps->vp == VIDEOPOSTCALL_FRAMESEQUENCE && vps->open) { C4dHelper::foreachObjectInHierarchy(vps->doc, vps->doc->GetFirstObject(), [&](BaseObject* pObject) -> bool { if (pObject->GetType() != Osphere) return true; BaseContainer* baseContainer = pObject->GetDataInstance(); if (baseContainer == nullptr) return true; if (!baseContainer->GetBool(PRIM_SPHERE_PERFECT)) return true; GePrint("Parametric sphere found! Turing off \"render perfect\"!"); baseContainer->SetBool(PRIM_SPHERE_PERFECT, false); return true; }); return RENDERRESULT_OK; } if (vps->vp == VIDEOPOSTCALL_INNER && vps->open) { // RayObjects of type O_SPHERE should not have been created now, // instead they are of type O_POLYGON return RENDERRESULT::RENDERRESULT_OK; } return RENDERRESULT::RENDERRESULT_OK; }
-
On 21/10/2014 at 04:25, xxxxxxxx wrote:
well thanks a lot , but I'm kinda confused now, what I understand is that videopost plugin is called "after" Cinema 4D ray object filling, so how this is working before the filling?
-
On 21/10/2014 at 06:21, xxxxxxxx wrote:
Search in the docu for these flags:
* VIDEOPOSTCALL_FRAMESEQUENCE
* VIDEOPOSTCALL_INNERThere are some more of those, where each is called in a fixed order with an open or close bool.
Execute is called for each step in the rendering pipeline twice. The VIDEOPOSTCALL_FRAMESEQUENCE is the first one before a rendering starts and before C4D performs any computations. VolumeData, for example, is not ready in this state, so setting the "render perfect" works
-
On 21/10/2014 at 06:24, xxxxxxxx wrote:
oh , thanks a lot for clarification