VRAY/VRAY_DemoMountain.C
#include "VRAY_DemoMountain.h"
#include <GEO/GEO_AttributeHandle.h>
#include <GU/GU_Detail.h>
#include <GU/GU_PrimPoly.h>
using namespace HDK_Sample;
#define MAX_SPLITS 8
#define UT_DEBUG 1
#include <UT/UT_Counter.h>
static UT_Counter theCount("Mountains");
static UT_Counter theTotal("TotalMountains");
static VRAY_ProceduralArg theArgs[] = {
VRAY_ProceduralArg("p0", "real", "-1 -1 0"),
VRAY_ProceduralArg("p1", "real", " 1 -1 0"),
VRAY_ProceduralArg("p2", "real", " 0 1 0"),
VRAY_ProceduralArg()
};
VRAY_Procedural *
allocProcedural(const char *)
{
return new VRAY_DemoMountain();
}
const VRAY_ProceduralArg *
getProceduralArgs(const char *)
{
return theArgs;
}
VRAY_DemoMountain::VRAY_DemoMountain(int splits)
: mySplits(splits)
{
theCount++;
theTotal++;
}
VRAY_DemoMountain::~VRAY_DemoMountain()
{
theCount--;
}
const char *
VRAY_DemoMountain::getClassName()
{
return "VRAY_DemoMountain";
}
int
VRAY_DemoMountain::initialize(const UT_BoundingBox *)
{
uint seed = 0xbabecafe;
myP[0].assign(-1, -1, 0, seed);
SYSfastRandom(seed);
myP[1].assign( 1, -1, 0, seed);
SYSfastRandom(seed);
myP[2].assign( 0, -1, 0, seed);
mySplits = 1;
import("p0", myP[0].pos.data(), 3);
import("p1", myP[1].pos.data(), 3);
import("p2", myP[2].pos.data(), 3);
return 1;
}
void
VRAY_DemoMountain::computeBounds(UT_BoundingBox &box, bool include_displace)
{
box.initBounds(myP[0].pos);
box.enlargeBounds(myP[1].pos);
box.enlargeBounds(myP[2].pos);
if (include_displace)
{
fpreal bounds = 0.5 / (fpreal)mySplits;
box.enlargeBounds(0, bounds);
}
}
void
VRAY_DemoMountain::getBoundingBox(UT_BoundingBox &box)
{
computeBounds(box, true);
fpreal bounds = 0.5 / (fpreal)mySplits;
box.initBounds(myP[0].pos);
box.enlargeBounds(myP[1].pos);
box.enlargeBounds(myP[2].pos);
box.enlargeBounds(0, bounds);
}
void
VRAY_DemoMountain::render()
{
fpreal lod;
UT_BoundingBox box;
computeBounds(box, false);
lod = getLevelOfDetail(box);
if (lod < 6 || mySplits > MAX_SPLITS)
{
fractalRender();
}
else
{
fractalSplit();
}
}
static void
edgeSplit(FractalPoint &P, const FractalPoint &p0, const FractalPoint &p1,
fpreal scale)
{
uint seed;
fpreal disp;
seed = (p0.seed + p1.seed)/2;
disp = SYSfastRandomZero(seed)*scale;
P.seed = seed;
P.pos = (p0.pos + p1.pos) * .5;
P.pos(2) += 0.25 * disp * distance3d(p0.pos, p1.pos);
}
void
VRAY_DemoMountain::fractalSplit()
{
VRAY_DemoMountain *kids[4];
int i;
fpreal scale;
scale = 1.0 / (fpreal)mySplits;
for (i = 0; i < 4; i++)
kids[i] = new VRAY_DemoMountain(mySplits+1);
for (i = 0; i < 3; i++)
{
kids[i]->myP[0] = myP[i];
edgeSplit(kids[i]->myP[1], myP[i], myP[(i+1)%3], scale);
}
for (i = 0; i < 3; i++)
{
kids[3]->myP[i] = kids[(i+1)%3]->myP[2] = kids[i]->myP[1];
}
for (i = 0; i < 4; i++)
{
openProceduralObject();
addProcedural(kids[i]);
closeObject();
}
}
void
VRAY_DemoMountain::fractalRender()
{
GU_Detail *gdp;
GU_PrimPoly *poly;
int i;
gdp = allocateGeometry();
poly = GU_PrimPoly::build(gdp, 3);
#if 0
UT_Vector3 clr;
uint seed = myP[0].seed + myP[1].seed + myP[2].seed;
clr.x() = SYSfastRandom(seed);
clr.y() = SYSfastRandom(seed);
clr.z() = SYSfastRandom(seed);
gdp->addDiffuseAttribute(GEO_PRIMITIVE_DICT);
GEO_AttributeHandle Cd = gdp->getPrimAttribute("Cd");
Cd.setElement(poly);
Cd.setV3(clr);
#endif
for (i = 0; i < 3; i++)
{
poly->getVertex(i).getPos().assign(myP[i].pos.x(),
myP[i].pos.y(),
myP[i].pos.z(),
1);
}
openGeometryObject();
addGeometry(gdp, 0);
closeObject();
}