#include <UT/UT_DSOVersion.h>
#include <RE/RE_Render.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GU/GU_Detail.h>
#include <GU/GU_PrimGroupClosure.h>
#include <GR/GR_Detail.h>
#include <GR/GR_RenderHook.h>
#include <GR/GR_RenderTable.h>
namespace HDK_Sample {
class GR_SimpleNoise : public GR_RenderHook
{
public:
GR_SimpleNoise() {}
virtual ~GR_SimpleNoise() {}
int getWireMask(GU_Detail * ,
const GR_DisplayOption * ) const
{
return ~GEOPRIMPOLY;
}
virtual void renderWire(GU_Detail *gdp,
RE_Render &ren,
const GR_AttribOffset &ptinfo,
const GR_DisplayOption *dopt,
float lod,
const GU_PrimGroupClosure *hidden_geometry);
int getShadedMask(GU_Detail * ,
const GR_DisplayOption * ) const
{
return ~GEOPRIMPOLY;
}
virtual void renderShaded(GU_Detail *gdp,
RE_Render &ren,
const GR_AttribOffset &ptinfo,
const GR_DisplayOption *dopt,
float lod,
const GU_PrimGroupClosure *hidden_geometry);
virtual const char *getName() const { return "GR_SimpleNoise"; }
protected:
void fillLineArray(UT_Vector3 *line, int step, unsigned seed);
void fillReversedLineArray(UT_Vector3 *line, int step,
GEO_Point *pt1, GEO_Point *pt2);
void renderLine(RE_Render &ren,
GEO_Point *pt1, GEO_Point *pt2,
float lod);
void renderQuad(RE_Render &ren, const UT_Vector3 &nml,
UT_Vector3 *left, UT_Vector3 *right,
UT_Vector3 *top, UT_Vector3 *bot,
int step);
};
}
using namespace HDK_Sample;
void
GR_SimpleNoise::fillLineArray(UT_Vector3 *line, int step, unsigned seed)
{
UT_Vector3 mid;
float dist;
if (step < 2)
return;
dist = distance3d(line[0], line[step]);
dist *= 0.1;
mid = line[0];
mid += line[step];
mid /= 2.0f;
mid.x() += dist * (UTrandom(seed) - 0.5f);
mid.y() += dist * (UTrandom(seed) - 0.5f);
mid.z() += dist * (UTrandom(seed) - 0.5f);
step >>= 1;
line[step] = mid;
if (step > 1)
{
fillLineArray(line, step, seed);
fillLineArray(&line[step], step, seed + step);
}
}
void
GR_SimpleNoise::fillReversedLineArray(UT_Vector3 *line, int step,
GEO_Point *pt1, GEO_Point *pt2)
{
int n1, n2, i;
unsigned seed;
GEO_Point *tmp;
bool reverse = false;
UT_Vector3 v3;
n1 = pt1->getNum();
n2 = pt2->getNum();
if (n1 > n2)
{
reverse = true;
tmp = pt1;
pt1 = pt2;
pt2 = tmp;
n1 = pt1->getNum();
n2 = pt2->getNum();
}
line[0] = pt1->getPos();
line[step] = pt2->getPos();
seed = UTwang_inthash(n1) ^ n2;
fillLineArray(line, step, seed);
if (reverse)
{
for (i = 0; i < step / 2; i++)
{
v3 = line[i];
line[i] = line[step - i];
line[step - i] = v3;
}
}
}
void
GR_SimpleNoise::renderLine(RE_Render &ren,
GEO_Point *pt1, GEO_Point *pt2,
float lod)
{
if (pt1->getNum() > pt2->getNum())
{
GR_SimpleNoise::renderLine(ren, pt2, pt1, lod);
return;
}
unsigned seed;
UT_Vector3 linearray[33];
int i;
int step;
step = (int)UTrint(lod * 2);
if (step > 5)
step = 5;
step = 1 << step;
linearray[0] = pt1->getPos();
linearray[step] = pt2->getPos();
seed = UTwang_inthash(pt1->getNum()) ^ pt2->getNum();
fillLineArray(linearray, step, seed);
ren.beginLine();
for (i = 0; i <= step; i++)
{
ren.vertex3DW(linearray[i].x(), linearray[i].y(), linearray[i].z());
}
ren.endLine();
}
void
GR_SimpleNoise::renderQuad(RE_Render &ren, const UT_Vector3 &nml,
UT_Vector3 *left, UT_Vector3 *right,
UT_Vector3 *top, UT_Vector3 *bot,
int step)
{
int i, j;
float u, v, ustep, vstep, mixfactor;
float n[3];
n[0] = -nml.x();
n[1] = -nml.y();
n[2] = -nml.z();
UT_Vector3 lr, tb;
UT_Vector3 v3;
ustep = vstep = 1.0f / (float) step;
u = 0.0f;
for (i = 0; i < step; i++)
{
ren.beginQuadStrip();
v = 0.0f;
for (j = 0; j <= step; j++)
{
tb = bot[i] * (1.0f - v) + top[i] * v;
lr = left[j] * (1.0f - u) + right[j] * u;
if (fabs(u - 0.5f) > fabs(v - 0.5f))
{
mixfactor = fabs(u - 0.5f) * 2;
}
else
{
mixfactor = 1.0f - fabs(v - 0.5f) * 2;
}
v3 = tb * (1.0f - mixfactor) + lr * mixfactor;
ren.n3DW(n);
ren.vertex3DW(v3.x(), v3.y(), v3.z());
tb = bot[i+1] * (1.0f - v) + top[i+1] * v;
lr = left[j] * (1.0f - u - ustep) + right[j] * (u + ustep);
if (fabs(u + ustep - 0.5f) > fabs(v - 0.5f))
{
mixfactor = fabs(u + ustep - 0.5f) * 2;
}
else
{
mixfactor = 1.0f - fabs(v - 0.5f) * 2;
}
v3 = tb * (1.0f - mixfactor) + lr * mixfactor;
ren.n3DW(n);
ren.vertex3DW(v3.x(), v3.y(), v3.z());
v += vstep;
}
ren.endQuadStrip();
u += ustep;
}
}
void
GR_SimpleNoise::renderWire(GU_Detail *gdp,
RE_Render &ren,
const GR_AttribOffset & ,
const GR_DisplayOption * ,
float lod,
const GU_PrimGroupClosure *hidden_geometry)
{
int i, nprim, nvtx, j, lj;
GEO_Primitive *prim;
nprim = gdp->primitives().entries();
for (i = 0; i < nprim; i++)
{
prim = gdp->primitives()(i);
if (hidden_geometry && hidden_geometry->containsPrim(prim))
continue;
if (!(prim->getPrimitiveId() & GEOPRIMPOLY))
continue;
nvtx = prim->getVertexCount();
if (((GEO_PrimPoly *)prim)->isClosed())
{
j = 0;
lj = nvtx-1;
}
else
{
j = 1;
lj = 0;
}
for (; j < nvtx; j++)
{
renderLine(ren,
prim->getVertex(lj).getPt(),
prim->getVertex(j).getPt(),
lod);
lj = j;
}
}
}
void
GR_SimpleNoise::renderShaded(GU_Detail *gdp,
RE_Render &ren,
const GR_AttribOffset & ,
const GR_DisplayOption * ,
float lod,
const GU_PrimGroupClosure *hidden_geometry)
{
int i, nprim, nvtx;
GEO_Primitive *prim;
nprim = gdp->primitives().entries();
for (i = 0; i < nprim; i++)
{
prim = gdp->primitives()(i);
if (hidden_geometry && hidden_geometry->containsPrim(prim))
continue;
if (!(prim->getPrimitiveId() & GEOPRIMPOLY))
continue;
nvtx = prim->getVertexCount();
if (nvtx != 4 ||
!((GEO_PrimPoly *)prim)->isClosed())
{
continue;
}
UT_Vector3 top[33], bot[33], left[33], right[33];
int step;
UT_Vector3 nml;
nml = ((GEO_PrimPoly *)prim)->computeNormal();
step = (int)UTrint(lod * 2);
if (step > 5)
step = 5;
step = 1 << step;
fillReversedLineArray(bot, step,
prim->getVertex(0).getPt(),
prim->getVertex(1).getPt());
fillReversedLineArray(top, step,
prim->getVertex(3).getPt(),
prim->getVertex(2).getPt());
fillReversedLineArray(left, step,
prim->getVertex(0).getPt(),
prim->getVertex(3).getPt());
fillReversedLineArray(right, step,
prim->getVertex(1).getPt(),
prim->getVertex(2).getPt());
renderQuad(ren, nml, left, right, top, bot, step);
}
}
void
newRenderHook(GR_RenderTable *table)
{
GR_SimpleNoise *hook = new GR_SimpleNoise;
table->addHook(hook, GR_RENDER_HOOK_VERSION);
}