/*
Intended for use with Mach Kobayashi's OmnidirectionalStereo Projection
plugin. For details about how to use his plugin with this Rif refer to:
www.fundza.com/devkit/rifplugins/omni_stereo/index.html
May 16 2016
Malcolm Kesson
*/
#include <RifPlugin.h>
#include <RifFilter.h>
#include <RixInterfaces.h>
#include <ri.h>
#include <string>
#include <rx.h>
#include <stdlib.h>
#include <stdio.h>
#define DEFAULT_STEREO_PLUGIN_NAME "OmnidirectionalStereo"
class OmniProjection_Rif : public RifPlugin {
public:
OmniProjection_Rif(std::string plugin_path, RtFloat eye_sep);
virtual ~OmniProjection_Rif() { }
virtual RifFilter &GetFilter() { return m_filter; }
virtual std::string join(std::string head, std::string tail);
// static void infoMsg(const char *str);
private:
RixMessages *m_msg;
RifFilter m_filter;
std::string m_plugin_path;
RtFloat m_interpupilaryDistance;
// Callback_____________________________________________________________
static RtVoid projection(RtToken name, RtInt, RtToken[], RtPointer[]);
};
//-----------------------------------------------------
// RifPluginManufacture
//-----------------------------------------------------
// For simplicity we assume that if a path to the Kobayashi plugin
// has been specified it does NOT contain spaces.
RifPlugin *RifPluginManufacture(int argc, char **argv) {
std::string defaultPath("./");
if(argc == 0) {
return new OmniProjection_Rif(defaultPath, -1);
}
std::vector <std::string> inputs;
if(argc == 1) {
// Tokenize and add to a list (vector) of inputs.
char *ptr = strtok(*argv, " ");
while(ptr) {
inputs.push_back(std::string(ptr));
ptr = strtok(NULL, " ");
}
}
else // multiple inputs
for(int n = 0; n < argc; n++)
inputs.push_back(std::string(argv[n]));
RtFloat fval = 2.0;
char *endPtr = NULL;
if(inputs.size() == 1) {
fval = strtod(inputs[0].c_str(), &endPtr);
// Not a number, therefore, assume its the path to
// the Projection plugin.
if(*endPtr)
return new OmniProjection_Rif(inputs[0], -1.0);
else
return new OmniProjection_Rif(defaultPath, fval);
}
else // the first input MUST be a path followed by float
{
fval = strtod(inputs[1].c_str(), &endPtr);
// Not a float...
if(*endPtr)
return new OmniProjection_Rif(inputs[0], -1.0);
return new OmniProjection_Rif(inputs[0], fval);
}
}
//-----------------------------------------------------
// OmniProjection_Rif
//-----------------------------------------------------
// Constructor
OmniProjection_Rif::OmniProjection_Rif(std::string path, RtFloat eye_sep) {
RixContext *rixContext = RxGetRixContext();
m_msg = (RixMessages*) rixContext->GetRixInterface(k_RixMessages);
m_plugin_path = path;
m_interpupilaryDistance = eye_sep;
m_filter.ProjectionV = projection;
m_filter.Filtering = RifFilter::k_Continue;
m_plugin_path = join(m_plugin_path, DEFAULT_STEREO_PLUGIN_NAME);
}
//-----------------------------------------------------
// Callback: projection
//-----------------------------------------------------
RtVoid OmniProjection_Rif::projection(RtToken name, RtInt nvals, RtToken tokens[], RtPointer params[]) {
OmniProjection_Rif *self = static_cast<OmniProjection_Rif*> (RifGetCurrentPlugin());
// Is there any sense in outputting the standard Projection rib statement?
// RiProjectionV(name, nvals, tokens, params);
// Ensure the Projection plugin uses it's default "interpupilaryDistance".
if(self->m_interpupilaryDistance == -1) {
RiProjectionV( (char*)self->m_plugin_path.c_str(), 0, NULL, NULL);
return;
}
RixContext *rixContext = RxGetRixContext();
RixTokenStorage *tok_store = static_cast<RixTokenStorage*>(rixContext->GetRixInterface(k_RixGlobalTokenData));
RtToken tok = (char*)tok_store->GetToken("float interpupilaryDistance");
RtToken token[] = { tok };
RtPointer param[] = { &self->m_interpupilaryDistance };
RiProjectionV( (char*)self->m_plugin_path.c_str(), 1, token, param);
}
//-----------------------------------------------------
// join file paths
//-----------------------------------------------------
std::string OmniProjection_Rif::join(std::string head, std::string tail) {
//std::replace(head.begin(), head.end(), '\\', '/');
//std::replace(tail.begin(), tail.end(), '\\', '/');
char lastChar = *head.rbegin();
return (lastChar != '/') ? head + '/' + tail : head + tail;
}
/*
void OmniProjection_Rif::infoMsg(const char *str) {
RixContext *rixContext = RxGetRixContext();
RixMessages *msg = (RixMessages*) rixContext->GetRixInterface(k_RixMessages);
msg->InfoAlways(str);
}
*/