VIDEOPOST_CUSTOMLENS missing?
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/10/2007 at 00:50, xxxxxxxx wrote:
User Information:
Cinema 4D Version: 9.5
Platform: Windows ;
Language(s) : C++ ;---------
Hallo,I'm trying to write a custom lense model in order to generate fisheye images or images with a non central projection model. My general idea was to write a Video Post plugin (which I have never done before...) and create rays via the described MSG_VIDEOPOST_CREATERAY concept. Now just trying out first steps I realized that neither MSG_VIDEOPOST_CREATERAY nor VIDEOPOST_CUSTOMLENS are defined in any headers. Later must be returned by GetRenderInfo() to get started in the first place. Both symbols are described in the 9.5 and 10.0 SDK reference.
So the question is: am I missing something? Is this a feature to come or a feature that has been?Thanks,
Bogumil -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/10/2007 at 01:47, xxxxxxxx wrote:
For which Cinema 4D version do you compile your plugin? It works fine for 10.5 here.
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 10/10/2007 at 06:13, xxxxxxxx wrote:
Hi,
I'm working on C4D 9.5, maybe here it's missing?
I had a look at c4d_videopostdata.h and it's not there.Thanks,
Bogumil -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 11/10/2007 at 01:01, xxxxxxxx wrote:
I tried it now with Cinema 4D 9.603 and it compiles without problems. Please update your Cinema installation to 9.603, it's a free update, and see if it still refuses to work.
cheers,
Matthias -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 12/10/2007 at 05:35, xxxxxxxx wrote:
Hallo Matthias,
thanks, the update did work: the needed defines are present and I was able to get to plugin to be registered and activated... Yet I am a bit confused. I have been looking for a point where I can calculate the ray which I want to send. I decided, that the ExecutePixel method looks suitable. My first try was to implement a parallel projection, which has no extrinsic parameters. So I wrote a ExecutePixel method, placed a huge cube in front of the "camera" and actived the plugin but after some calculations the image is black!
Here the code:
> _
> void MipCameraModel::
> ExecutePixel(PluginVideoPost* node, PixelPost* pp, LONG x, LONG subx, LONG suby)
> {
> VideopostCreateRay ray;
> ray.x = x;
> ray.y = pp->line;
> ray.p.x = x;
> ray.p.y = pp->line;
> ray.p.z = 0.0;
> ray.v.x = x;
> ray.v.y = pp->line;
> ray.v.z = 1.0;
> std::stringstream callUp;
> callUp<<"MipCameraModel::ExecutePixel for "<<x<<", "<<pp->line;
>
> String dbgmsg(callUp.str().c_str());
> GePrint(dbgmsg);
> Message(node, MSG_VIDEOPOST_CREATERAY, &ray;);
> }
> _I'm grateful for any comments, critics, suggestions
Bogumil
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 13/10/2007 at 07:16, xxxxxxxx wrote:
Hallo,
ok mabe I should ask more precise questions! What I am trying to do is to write a plugin that is capable of generating the initial rays for each image pixel. (For a perspective camera this would be a ray originating at the camera center with a directional component pointing from the camera center towards the pixel position in the 3D scene frame.) The first question then would be: Is it possible to write a plugin which is only changing this part of the raytracing process? Meaning that the plugin does not have to trace any rays and generate any fragment information?
If this is possible: is a VideoPostPlugin the right plugin type? I assumed so because of the VIDEOPOST_CUSTOMLENS return type of the GetRenderInfo() method of the VideoPostData class. From there the SDK reference led me to the point that after setting this return type, the plugin can provide (its own?!) rays. The reference states that this is done by means of sending a Message with the type MSG_VIDEOPOST_CREATERAY and a pointer to the data of a Struct type named VideopostCreateRay. At this point I am not sure about several things:
- For which object do I call the Message method or "to whom do I send the message?"
- Where/when do I have to send the ray(s) (Execute or ExecutePoint)?
- Where is the ray data stored that is send, or do I have to allocate the ray(s) in free mem?
.
What I did to try some things out was to implement a VideoPost plugin that is reading out the ray data from the VolumeData and writing it onto the console. The plugin code (without the 'default' class declaration) looks like this:
> _
> /* Class declaration
> ...
> */
> void RayReadOut::
> PrintOpticalRay(VideoPostStruct* vps, LONG x, LONG y)
> {
> Ray ray;
> vps- >vd->GetRay(x, y, &ray;);
> std::stringstream output;
> output<<"("<<x<<", "<<y
> <<") : ("<<ray.p.x<<","<<ray.p.y<<","<<ray.p.z
> <<") -> ("<<ray.v.x<<","<<ray.v.y<<","<<ray.v.z<<")";
> String dbgstr(output.str().c_str());
> GePrint(dbgstr);
> }
>
> LONG RayReadOut::
> Execute(PluginVideoPost *node, VideoPostStruct *vps)
> {
> //execute when entering inner processing
> if(vps->open && vps->vp==VP_INNER) {
>
> GePrint(" -= RayReadOut::Execute =- ");
>
> RayParameter *ray = vps->vd->GetRayParameter(); // only in VP_INNER & VP_RENDER
>
> //get current image region
> LONG xMin,yMin,xMax,yMax;
> xMin = ray->left;
> yMin = ray->top;
> xMax = ray->right;
> yMax = ray->bottom;
>
> //print optical rays passing through image region corners to console:
> PrintOpticalRay(vps, xMin, yMin);
> PrintOpticalRay(vps, xMin, yMax);
> PrintOpticalRay(vps, xMax, yMax);
> PrintOpticalRay(vps, xMax, yMin);
>
> }
> return RAY_OK;
> }
> _Activating this 'ReadOut' plugin when rendering through a parallel projection camera, which is positioned at the scene origin and having all rotation angles set to zero, delivers reasonable ray data for the corner pixels. The moment I activate my plugin which returns VIDEOPOST_CUSTOMLENS through GetRenderInfo() all rays aquired origin in (0,0,0) and point to (0,0,0). I tried all types of passing rays through messages I could think of (like in my previous post), but nothing changes this behaviour.
I'm grateful for any help!
Bogumil -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 25/10/2007 at 12:54, xxxxxxxx wrote:
This is one of the areas of the SDK where an example is really needed for a long time. I've tried similar stuff to no avail.
Kabe
-
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 25/10/2007 at 23:57, xxxxxxxx wrote:
Hi Kabe,
with the help of Katachi (alias 3D Designer) (thanx again) I managed to write a VP for an ideal fisheye lens:
> _
> /////////////////////////////////////////////////////////////
> // CINEMA4D VP PLUGIN: Ideal Fisheye Camera VideoPost //
> /////////////////////////////////////////////////////////////
>
> // includes
>
> #include "c4d.h"
> #include "c4d_symbols.h"
>
> class IdealFisheyeCamera : public VideoPostData
> {
> public:
> // virtual Bool Init(GeListNode* node);
> static NodeData *Alloc(void) { return gNew IdealFisheyeCamera; }
> virtual LONG GetRenderInfo(PluginVideoPost *node) {
> return VIDEOPOST_CUSTOMLENS;
> }
> virtual Bool Message(GeListNode* node, LONG type, void* data);
> };
>
>
>
> /** Calculates the ray for the current pixel simulating a ideal fisheye camera
> * with field-of-view of 180Deg.
> * It uses the active render camera's pose (position and orientation) for the
> * pose of the fisheye camera. The optical axis is mapped to the active image center.
> * The radius is chosen so that the whole FoV fits into the image.
> */
> Bool IdealFisheyeCamera::
> Message(GeListNode* node, LONG type, void* data) {
>
> if(type == MSG_VIDEOPOST_CREATERAY) {
> VideopostCreateRay* ray = (VideopostCreateRay* )(data);
>
> if(ray != NULL) {
> BaseDocument* actdoc = GetActiveDocument();
> BaseDraw* basedraw = actdoc->GetRenderBaseDraw();
>
> RenderData* renderdata = actdoc->GetActiveRenderData();
> BaseContainer* bc = renderdata->GetDataInstance();
> LONG xres = bc->GetLong(RDATA_XRES);
> LONG yres = bc->GetLong(RDATA_YRES);
>
> // centering optical axis around image center:
> Real ppx = static_cast<Real>(xres)/2.0;
> Real ppy = static_cast<Real>(yres)/2.0;
>
> Real maxRad = (ppx<ppy) ? ppx-1 : ppy-1;//choosing the maximal viewing range
> Real angleStep = 1.57/maxRad; //linear mapping of radius to angle (90Deg = max)
>
>
> double x = ray->x-ppx;
> double y = ray->y-ppy;
> Real r = static_cast<Real>(sqrt(x*x + y*y));
>
> if(r<maxRad) {//do not render outside of FoV
>
> //calc polar coordinates
> Real phi = static_cast<Real>(atan2(ray->y-ppy, ray->x-ppx));
> Real theta = r*angleStep;
>
> CameraObject* cam = (CameraObject* )basedraw->GetSceneCamera(actdoc);
> Matrix globalPose = cam->GetMg();
>
> //calculate ray direction v in global coordinates
> Vector H = globalPose.v1;
> Vector V = globalPose.v2;
> Vector A = globalPose.v3;
> H *= (cos(phi)*sin(theta));
> V *= -(sin(phi)*sin(theta));
> A *= cos(theta);
> Vector v = H+V+A;
>
> ray->p = LVector(globalPose.off.x, globalPose.off.y, globalPose.off.z);
> ray->v = LVector(v.x, v.y, v.z);
>
>
> } else {
> return TRUE;
> }
> } else {
> GePrint("send data is not allocated!");
> return FALSE;
> }
> }
> return TRUE;
> }
>
>
> // be sure to use a unique ID obtained from www.plugincafe.com
> #define ID_VPIdealFisheyeCamera 1000001
>
> Bool RegisterIdealFisheyeCamera(void)
> {
> // decide by name if the plugin shall be registered - just for user convenience
> String name=GeLoadString(IDS_IDEAL_FISHEYE_CAMERAMODEL); if (!name.Content()) return TRUE;
> return RegisterVideoPostPlugin(ID_VPIdealFisheyeCamera,name,0,IdealFisheyeCamera::Alloc,"",0,0);
>
> }
>
> _This implementation is not efficient but for a first shot ...
Cheers,
Bogumil -
THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/10/2007 at 00:17, xxxxxxxx wrote:
Thanks for sharing your source code Bogumil. It would be nice if more people would do this.
cheers,
Matthias