#include <RixPattern.h>
#include <RixShadingUtils.h>
#include <RixShading.h>
//#include <RixInterfaces.h>
#include <cstring>
class CutrFaceColor : public RixPattern {
public:
CutrFaceColor();
virtual ~CutrFaceColor() { }
virtual int Init(RixContext &, char const *pluginpath);
virtual RixSCParamInfo const *GetParamTable();
virtual void Finalize(RixContext &) { }
virtual int ComputeOutputParams(RixShadingContext const *ctx,
RtInt *noutputs,
OutputSpec **outputs,
RtConstPointer instanceData,
RixSCParamInfo const *ignored);
private:
RixMessages *m_msg;
RixShadeFunctions *m_shd; // Shading functions in RixInterfaces.h
RtColorRGB m_xcolor;
RtColorRGB m_ycolor;
RtColorRGB m_zcolor;
RtColorRGB m_base_color;
RtFloat m_base_amount;
};
CutrFaceColor::CutrFaceColor():
m_msg(NULL),
m_shd(NULL),
m_xcolor(1,0,0),
m_ycolor(0,1,0),
m_zcolor(0,0,1),
m_base_color(1,1,1),
m_base_amount(1)
{ }
int CutrFaceColor::Init(RixContext &ctx, char const *pluginpath) {
m_msg = (RixMessages*)ctx.GetRixInterface(k_RixMessages);
m_shd = (RixShadeFunctions*)ctx.GetRixInterface(k_RixShadeFunctions);
// Uncomment the next three lines if a rib Option will be queried.
//RixRenderState *rstate = (RixRenderState*)ctx.GetRixInterface(k_RixRenderState);
//RixRenderState::Type optType;
//RtInt optNumValues, err;
// Example of using messaging,
// m_msg->Info("%f\n", a_float_value);
return (!m_msg) ? 1 : 0;
}
RixSCParamInfo const *CutrFaceColor::GetParamTable() {
static RixSCParamInfo s_ptable[] = {
// Output
RixSCParamInfo("resultRGB", k_RixSCColor, k_RixSCOutput),
// Inputs
RixSCParamInfo("xcolor", k_RixSCColor),
RixSCParamInfo("ycolor", k_RixSCColor),
RixSCParamInfo("zcolor", k_RixSCColor),
RixSCParamInfo("coord_name", k_RixSCString),
RixSCParamInfo("base_color", k_RixSCColor),
RixSCParamInfo("base_amount", k_RixSCFloat),
RixSCParamInfo() // end of table
};
return &s_ptable[0];
}
enum paramIndex {
k_resultRGB = 0,
k_xcolor,
k_ycolor,
k_zcolor,
k_coord_name,
k_base_color,
k_base_amount
};
int CutrFaceColor::ComputeOutputParams(RixShadingContext const *ctx,
RtInt *noutputs,
OutputSpec **outputs,
RtConstPointer instanceData,
RixSCParamInfo const *ignored) {
// Uncomment the next three lines if a rib Attribute will be queried. Note
// that Rib Options should be queried in the init() method - not here!
//RixRenderState *rstate = (RixRenderState*)ctx->GetRixInterface(k_RixRenderState);
//RixRenderState::Type attrType;
//RtInt attrNumValues, err;
// OUTPUTS BEGIN____________________________________
// Allocate memory for the OutputSpec data structure.
RixShadingContext::Allocator pool(ctx);
OutputSpec *outSpec = pool.AllocForPattern<OutputSpec>(1);
*outputs = outSpec;
// Allocate memory for each output.
RtColorRGB *resultRGB = pool.AllocForPattern<RtColorRGB>(ctx->numPts);
// Connect the output(s) to the OutputSpec.
*noutputs = 1;
outSpec[0].paramId = k_resultRGB;
outSpec[0].detail = k_RixSCVarying;
outSpec[0].value = resultRGB;
// INPUTS BEGIN____________________________________
bool varying = true;
//bool uniform = false;
// Declare a pointer for each input then obtain their values
// using EvalParam().
RtColorRGB const *xcolor;
RtColorRGB const *ycolor;
RtColorRGB const *zcolor;
RtConstString *coord_namePtr;
RtColorRGB const *base_color;
RtFloat const *base_amount;
ctx->EvalParam(k_xcolor, -1, &xcolor, &m_xcolor, varying);
ctx->EvalParam(k_ycolor, -1, &ycolor, &m_ycolor, varying);
ctx->EvalParam(k_zcolor, -1, &zcolor, &m_zcolor, varying);
ctx->EvalParam(k_coord_name, -1, &coord_namePtr);
ctx->EvalParam(k_base_color, -1, &base_color, &m_base_color, varying);
ctx->EvalParam(k_base_amount, -1, &base_amount, &m_base_amount, varying);
// Assign an array of normalized shading normals to Nn.
// Copy the original Nn data to tformNn. Transform will
// over-write the original tNn data.
RtNormal3 const *Nn;
ctx->GetBuiltinVar(RixShadingContext::k_Nn, &Nn);
RtNormal3 *tNn = pool.AllocForPattern<RtNormal3>(ctx->numPts);
memcpy(tNn, Nn, sizeof(RtNormal3) * ctx->numPts);
if(strlen(*coord_namePtr) == 0)
ctx->Transform(RixShadingContext::k_AsNormals, "current", "object", tNn, NULL);
else
ctx->Transform(RixShadingContext::k_AsNormals, "current", *coord_namePtr, tNn, NULL);
RtVector3 vecx = RtVector3(1.0, 0, 0);
RtVector3 vecy = RtVector3(0, 1.0, 0);
RtVector3 vecz = RtVector3(0, 0, 1.0);
RtColorRGB white = RtColorRGB(1.0, 1.0, 1.0);
RtFloat dot;
// Assign values to the output(s).
for(int i = 0; i < ctx->numPts; i++) {
// Ensure the length of the normal does not exceed 1.0.
tNn[i].Normalize();
dot = fabs(tNn[i].Dot(vecx));
resultRGB[i] = RixMix(white, xcolor[i], dot);
dot = fabs(tNn[i].Dot(vecy));
resultRGB[i] = RixMix(resultRGB[i], ycolor[i], dot);
dot = fabs(tNn[i].Dot(vecz));
resultRGB[i] = RixMix(resultRGB[i], zcolor[i], dot);
// Finally, tint the result with the base color
RtColorRGB rgb = RixMix(white, base_color[i], base_amount[i]);
resultRGB[i] *= rgb;
//resultRGB[i] = RixMix(resultRGB[i], base_color[i], base_amount[i]);
}
return 0;
}
RIX_PATTERNCREATE {
return new CutrFaceColor();
}
RIX_PATTERNDESTROY {
delete((CutrFaceColor*)pattern);
}