HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
karma_procedurals/BRAY_HdBox.C
/*
* 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.
*
*----------------------------------------------------------------------------
* Karma Procedural Scene Example
*/
#include "BRAY_HdBox.h"
#include <UT/UT_ErrorLog.h>
using namespace UT::Literal;
using namespace HDK_Sample;
namespace
{
// Literal string tokens
static constexpr UT_StringLit theToken("box_scene");
static constexpr UT_StringLit theBoxPos("boxpos");
static constexpr UT_StringLit theBoxSize("boxsize");
// Simple static factory
getFactory()
{
static BRAY_HdBox theFactory;
return theFactory;
}
// Simple class to build out params
class ParamListBuilder
{
public:
using Params = BRAY_AttribList::Attrib;
ParamListBuilder()
{
// build the list for our procedural here
Params parms[] = {
{
theBoxPos.asHolder(),
3,
},
{
theBoxSize.asHolder(),
1,
},
};
myParms = UTmakeUnique<BRAY_AttribList>(
parms, SYSarraySize(parms), false);
}
};
// Derive our procedural from the procedural scene, so all we have
// to implement is the updateScene(), and doSetParameters() methods
class BoxSceneProc final : public BRAY_ProceduralScene
{
public:
BoxSceneProc()
: myBox()
, myInstance()
, myDisplayColor(1, 1, 1)
, myBoxPos(0, 0, 0)
, myBoxSize(1)
{}
bool updateScene() override
{
// Reset and get the scene pointer
this->reset();
BRAY::ScenePtr scene = this->scene();
// Create a bounding box of our desired size
UT_Vector3D corner(myBoxSize, myBoxSize, myBoxSize);
corner /= 2;
bbox.initBounds(-corner);
bbox.enlargeBounds(corner);
// Quick little random colour
uint seed = SYSpointerHash(this);
while (myDisplayColor.maxComponent() < .7)
{
myDisplayColor = UT_Vector3(SYSfastRandom(seed),
SYSfastRandom(seed),
SYSfastRandom(seed));
}
// GT attributes can be added to the prim and will be picked up
// and evaluated by the procedural automatically
attribs << GT_Attribute("detail color64 displayColor",
myDisplayColor.data());
// Create a GT primitive using the primitive builder
auto &&prim = GT_PrimitiveBuilder::box(err, bbox, attribs);
if (!prim)
{
UT_ErrorLog::errorOnce("Error creating GT box prim {}", err.getErrors());
return false;
}
// Create the BRAY::ObjectPtr from the GT primitive box we constructed
// All BRAY::ObjectPtrs require a material, so we assing a dummy material here
// NOTE: The materials here will not be respected Karma, Karma will instead use
// any materials on the actual procedural object.
// To have finer control over the individual objects materials attributes
// and custom shaders must be used
myBox.setMaterial(scene,
scene.createMaterial("default"_sh),
scene.objectProperties());
if (!myBox)
{
UT_ErrorLog::errorOnce("Error creating BRAY mesh");
return false;
}
// Objects must be instanced to be added to a BRAY::ScenePtr
// Create the transform to instance our box to our box position
UT_Matrix4D xform;
xform.identity();
xform.translate(myBoxPos);
xforms.append(BRAY::SpacePtr(xform));
// Create the instance with the box we created and a unique instance name
myInstance = BRAY::ObjectPtr::createInstance(myBox, theToken.asHolder());
if (!myInstance)
{
UT_ErrorLog::errorOnce("Error creating BRAY instance");
return false;
}
// Set the instance transform
myInstance.setInstanceTransforms(xforms);
// Have to update the scene with the new instance
scene.updateObject(myInstance, BRAY_EVENT_NEW);
return true;
}
void update(BRAY_EventType event) override
{
UTdebugFormat("Update {}", className());
}
void doSetParameter(
const UT_StringRef &key,
const int32 *values,
int n) override
{
}
void doSetParameter(
const UT_StringRef &key,
const int64 *values,
int n) override
{
}
void doSetParameter(
const UT_StringRef &key,
const fpreal32 *values,
int n) override
{
if (key == theBoxPos && n == 3)
{
myBoxPos.x() = values[0];
myBoxPos.y() = values[1];
myBoxPos.z() = values[2];
}
else if (key == theBoxSize && n == 1)
{
myBoxSize = values[0];
}
}
void doSetParameter(
const UT_StringRef &key,
const fpreal64 *values,
int n) override
{
if (key == theBoxPos && n == 3)
{
myBoxPos.x() = values[0];
myBoxPos.y() = values[1];
myBoxPos.z() = values[2];
}
else if (key == theBoxSize && n == 1)
{
myBoxSize = values[0];
}
}
void doSetParameter(
const UT_StringRef &key,
const UT_StringHolder *values,
int n) override
{
}
private:
BRAY::ObjectPtr myInstance;
UT_Vector3D myDisplayColor;
UT_Vector3D myBoxPos;
fpreal myBoxSize;
};
}
BRAY_HdBox::BRAY_HdBox()
: BRAY_ProceduralFactory(theToken.asHolder())
{
}
BRAY_HdBox::~BRAY_HdBox()
{
}
BRAY_HdBox::create() const
{
return new BoxSceneProc;
}
/// Return the list of parameters, which are attributes of the procedural that
/// can be set by Karma. These parameters can control the behaviour of the
/// procedural.
/// In this example, the parameters are the radius and the color of the sphere.
BRAY_HdBox::paramList() const
{
// Thread safe static initialization
static ParamListBuilder builder;
return builder.myParms.get();
}
void
{
getFactory();
}