#include <math.h>
#include <maya/MPxNode.h>
#include <maya/MIOStream.h>
#include <maya/MString.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnMatrixAttribute.h>
#include <maya/MFloatVector.h>
#include <maya/MFloatPoint.h>
#include <maya/MFnPlugin.h>
#ifdef LINUX
#define fsqrt sqrtf
#include <stdlib.h>
#endif
class R3 {
public:
R3(float a, float b, float c): x(a), y(b), z(c) {}
R3() {}
public:
float x;
float y;
float z;
};
static void initCellFunc();
static void cellFunc(const R3 &, float &n0, float &f1, float &f2);
{
public:
Cell3D();
~Cell3D() override;
static void * creator();
private:
};
#define MAKE_INPUT(attr) \
CHECK_MSTATUS( attr.setKeyable(true) ); \
CHECK_MSTATUS( attr.setStorable(true) ); \
CHECK_MSTATUS( attr.setReadable(true) ); \
CHECK_MSTATUS( attr.setWritable(true) );
#define MAKE_OUTPUT(attr) \
CHECK_MSTATUS( attr.setKeyable(false) ); \
CHECK_MSTATUS( attr.setStorable(false) ); \
CHECK_MSTATUS( attr.setReadable(true) ); \
CHECK_MSTATUS( attr.setWritable(false) );
void Cell3D::postConstructor( )
{
setMPSafe(true);
}
Cell3D::Cell3D()
{
}
Cell3D::~Cell3D()
{
}
void * Cell3D::creator()
{
return new Cell3D();
}
{
MAKE_INPUT(nAttr);
MAKE_INPUT(nAttr);
aPlaceMat = mAttr.
create(
"placementMatrix",
"pm",
MAKE_INPUT(mAttr);
MAKE_INPUT(nAttr);
MAKE_OUTPUT(nAttr);
MAKE_OUTPUT(nAttr);
MAKE_OUTPUT(nAttr);
aOutBorderDist = nAttr.
create(
"borderDistance",
"bd",
MAKE_OUTPUT(nAttr);
MAKE_OUTPUT(nAttr);
MAKE_OUTPUT(nAttr);
return MS::kSuccess;
}
{
if ( (plug != aOutColor) && (plug.
parent() != aOutColor) &&
(plug != aOutAlpha) &&
(plug != aOutBorderDist) &&
(plug != aOutF0) && (plug != aOutF1) && (plug != aOutN0)
)
return MS::kUnknownParameter;
q *= m;
float n0, f0, f1;
cellFunc(R3(q.x, q.y, q.z), n0, f0, f1);
outHandle.
asFloat() = 0.5f*(f1 - f0);
outColor = cGain * f0 + cOff;
return MS::kSuccess;
}
{
const MString UserClassify(
"texture/3d" );
MFnPlugin plugin( obj, PLUGIN_COMPANY,
"4.5",
"Any" );
Cell3D::creator, Cell3D::initialize,
initCellFunc();
return MS::kSuccess;
}
{
return MS::kSuccess;
}
#define N_CELLS 1000
static int permuteTable[N_CELLS*2];
static void initPermute()
{
int i;
for (i = 0; i < N_CELLS; ++i) {
permuteTable[i] = i;
}
for (i = N_CELLS - 1; i >= 1; --i) {
int n = lrand48() % (i + 1);
int tmp = permuteTable[n];
permuteTable[n] = permuteTable[i];
permuteTable[i] = tmp;
}
for (i = 0; i < N_CELLS; ++i) {
permuteTable[i + N_CELLS] = permuteTable[i];
}
}
static int fold(int i, int j, int k)
{
if (i < 0) i = (i + N_CELLS*(i/N_CELLS + 1)) % N_CELLS;
else i %= N_CELLS;
if (j < 0) j = (j + N_CELLS*(j/N_CELLS + 1)) % N_CELLS;
else j %= N_CELLS;
if (k < 0) k = (k + N_CELLS*(k/N_CELLS + 1)) % N_CELLS;
else k %= N_CELLS;
return permuteTable[permuteTable[permuteTable[i] + j] + k];
}
#define N_CELLS 1000
static R3 CellSampleTable[N_CELLS];
static void initCellFunc()
{
int i;
srand48(10);
for (i = 0; i < N_CELLS; ++i) {
CellSampleTable[i] = R3((float)drand48(),
(float)drand48(),
(float)drand48());
}
initPermute();
}
static inline float sqr(float t) { return t*t; }
static inline float distance2(const R3 &a, const R3 &b)
{
float t = sqr(b.x - a.x) + sqr(b.y - a.y) + sqr(b.z - a.z);
return t;
}
static void cellFunc(const R3 &p, float &n0, float &f0, float &f1)
{
R3 q = p;
int i = (int)floorf(q.x);
int j = (int)floorf(q.y);
int k = (int)floorf(q.z);
q.x -= i;
q.y -= j;
q.z -= k;
int index = fold(i,j,k);
float minDist = distance2(CellSampleTable[index], q);
float minDist2 = 2.0;
int k0;
k0 = index;
R3 q1;
for (int ii = -1; ii <= 1; ++ii) {
q1.x = q.x - ii;
int i1 = i + ii;
for (int jj = -1; jj <= 1; ++jj) {
q1.y = q.y - jj;
int j1 = j + jj;
for (int kk = -1; kk <= 1; ++kk) {
if (!ii && !jj && !kk) continue;
q1.z = q.z - kk;
int k1 = k + kk;
index = fold(i1, j1, k1);
float t = distance2(CellSampleTable[index], q1);
if (minDist > t) {
minDist2 = minDist;
minDist = t;
k0 = index;
}
else if (minDist2 > t) {
minDist2 = t;
}
}
}
}
f0 = sqrtf(minDist);
f1 = sqrtf(minDist2);
n0 = k0/(float)(N_CELLS);
}