HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RAY/RAY_DemoMountain.C
/*
* Copyright (c) 2024
* Side Effects Software Inc. All rights reserved.
*
* Redistribution and use of Houdini Development Kit samples in source and
* binary forms, with or without modification, are permitted provided that the
* following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. The name of Side Effects Software may not be used to endorse or
* promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*----------------------------------------------------------------------------
* This is a sample procedural DSO
*/
#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 RAY_ProceduralArg theArgs[] = {
RAY_ProceduralArg("p0", "real", "-1 -1 0"),
RAY_ProceduralArg("p1", "real", " 1 -1 0"),
RAY_ProceduralArg("p2", "real", " 0 1 0"),
};
{
public:
: RAY_ProceduralFactory::ProcDefinition("demomountain")
{
}
RAY_Procedural *create() const override
{ return new RAY_DemoMountain(); }
RAY_ProceduralArg *arguments() const override { return theArgs; }
};
void
{
factory->insert(new ProcDef);
}
: mySplits(splits)
{
theCount++;
theTotal++;
}
RAY_DemoMountain::~RAY_DemoMountain()
{
theCount--;
}
const char *
{
return "RAY_DemoMountain";
}
int
{
uint seed = 0xbabecafe;
myP[0].assign(-1, -1, 0, seed);
SYSfastRandom(seed); // Permute seed
myP[1].assign( 1, -1, 0, seed);
SYSfastRandom(seed); // Permute seed
myP[2].assign( 0, -1, 0, seed);
// Get parameter values
import("p0", myP[0].pos.data(), 3);
import("p1", myP[1].pos.data(), 3);
import("p2", myP[2].pos.data(), 3);
return 1;
}
void
RAY_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.expandBounds(0, bounds);
}
}
void
{
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.expandBounds(0, bounds);
}
void
{
// Invoke the measuring code on the bounding box to determine the level of
// detail. The level of detail is the square root of the number of pixels
// covered by the bounding box (with all shading factors considered).
// However, for computing LOD, we do *not* want to include displacement
// bounds
computeBounds(box, false);
lod = getLevelOfDetail(box);
{
// Render geometry
}
else
{
// Split into child procedurals
}
}
static void
edgeSplit(FractalPoint &P, const FractalPoint &p0, const FractalPoint &p1,
{
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
{
RAY_DemoMountain *kids[4];
int i;
scale = 1.0 / (fpreal)mySplits;
for (i = 0; i < 4; i++)
kids[i] = new RAY_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++)
{
child->addProcedural(kids[i]);
}
}
void
{
// Build some geometry
GU_PrimPoly *poly = GU_PrimPoly::build(geo.get(), 3);
#if 0
// Optionally, create a primitive color attribute "Cd"
uint seed = myP[0].seed + myP[1].seed + myP[2].seed;
clr.x() = SYSfastRandom(seed);
clr.y() = SYSfastRandom(seed);
clr.z() = SYSfastRandom(seed);
Cd.set(poly->getMapOffset(), clr);
#endif
for (int i = 0; i < 3; i++)
{
geo->setPos3(poly->getPointOffset(i), myP[i].pos);
}
// Now, add the geometry to mantra.
child->addGeometry(geo);
}