hello,
We don't have example for this, I've write an example with the really minimum.
This videopost will only be available with the standard render.
You have to define for each pixel where you are ( dst->p) and where you are looking to (dst->v) (ray position and ray direction)
This is for render time, if you want to create a Lens Effect for the viewport this is a bit more complicated.
I hope this will help while we create a final example.
#include "c4d_videopost.h"
#include "c4d_baseobject.h"
#include "c4d_tools.h"
#include "c4d_basedocument.h"
#include "c4d_basedraw.h"
#include "c4d_resource.h"
#include "c4d_gui.h"
#include "drendersettings.h"
class VP_PC11585 : public VideoPostData
{
INSTANCEOF(VP_PC11585, VideoPostData);
public:
static NodeData* Alloc() { return NewObjClear(VP_PC11585); }
virtual VIDEOPOSTINFO GetRenderInfo(BaseVideoPost *node);
virtual void CreateRay(Ray* dst, Float x, Float y);
virtual RENDERRESULT Execute(BaseVideoPost* vp, VideoPostStruct* vps);
virtual Bool Init(GeListNode* node);
virtual Bool RenderEngineCheck(BaseVideoPost* node, Int32 id);
private:
Matrix camMg; /// Will store the camera matrix
Int32 m_xres, m_yres; /// Render size in parameters
};
VIDEOPOSTINFO VP_PC11585::GetRenderInfo(BaseVideoPost *node) {
// The videopost will provide custom lens rays with VideoPostData::CreateRay.
return VIDEOPOSTINFO::CUSTOMLENS;
}
Bool VP_PC11585::Init(GeListNode *node) {
return true;
}
RENDERRESULT VP_PC11585::Execute(BaseVideoPost *vp, VideoPostStruct *vps)
{
if (vps->vp == VIDEOPOSTCALL::INNER && vps->open && *vps->error == RENDERRESULT::OK && !vps->thread->TestBreak())
{
const RayCamera* cam = vps->vd->GetRayCamera();
if (cam == nullptr)
return RENDERRESULT::OUTOFMEMORY;
// Retrieves the camera matrix
camMg = cam->m;
// Store the image resolution
m_xres = vps->vd->GetRayParameter()->xres;
m_yres = vps->vd->GetRayParameter()->yres;
}
return RENDERRESULT::OK;
}
void VP_PC11585::CreateRay(Ray *dst, Float x, Float y) {
Float ppx = m_xres / 2.0;
Float ppy = m_yres / 2.0;
// Projection 360° in probe render (circle)
// centering optical axis around image center:
// Check if width or height is the larger
Float maxRad = (ppx < ppy) ? ppx - 1 : ppy - 1;
// Linear mapping of radius to angle (90 Deg = max)
Float angleStep = PI / maxRad;
Float newx = x - ppx;
Float newy = y - ppy;
Float r = sqrt(newx * newx + newy * newy);
// Do not render outside of radius
if (r < maxRad)
{
// Calculates polar coordinates
Float phi = atan2(y - ppy, x - ppx);
Float theta = r * angleStep;
// Calculates ray direction v in global coordinates
Vector H = camMg.sqmat.v1;
Vector V = camMg.sqmat.v2;
Vector A = camMg.sqmat.v3;
H *= cos(phi) * sin(theta);
V *= -sin(phi) * sin(theta);
A *= cos(theta);
Vector v = H + V + A;
dst->p = camMg.off;
dst->v = v;
}
}
Bool VP_PC11585::RenderEngineCheck(BaseVideoPost *node, Int32 id) {
// Only supports standard render
if (id == RDATA_RENDERENGINE_STANDARD)
{
return true;
}
return false;
}
Cheers
Manuel