HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tetprim/GEO_PrimTetra.h
/*
* 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.
*/
/*
* COMMENTS: This is an HDK example for making a custom tetrahedron primitive type.
*/
#ifndef __HDK_GEO_PrimTetra__
#define __HDK_GEO_PrimTetra__
#include <GA/GA_Detail.h>
#include <GA/GA_Types.h>
#include <UT/UT_Vector3.h>
namespace HDK_Sample {
class GEO_PrimTetra : public GEO_Primitive
{
protected:
/// NOTE: The destructor should only be called from GA_PrimitiveList,
/// via a GA_Primitive pointer.
~GEO_PrimTetra() override;
public:
/// NOTE: To create a new primitive owned by the detail, call
/// GA_Detail::appendPrimitive or appendPrimitiveBlock on
/// the detail, not this constructor.
/// @{
/// Required interface methods
bool isDegenerate() const override;
bool getBBox(UT_BoundingBox *bbox) const override;
void reverse() override;
UT_Vector3D computeNormalD() const override;
UT_Vector3 computeNormal() const override;
void copyPrimitive(const GEO_Primitive *src) override;
void copySubclassData(const GA_Primitive *source) override;
// Take the whole set of points into consideration when applying the
// point removal operation to this primitive. The method returns 0 if
// successful, -1 if it failed because it would have become degenerate,
// and -2 if it failed because it would have had to remove the primitive
// altogether.
int detachPoints(GA_PointGroup &grp) override;
/// Before a point is deleted, all primitives using the point will be
/// notified. The method should return "false" if it's impossible to
/// delete the point. Otherwise, the vertices should be removed.
bool dry_run=false) override;
bool dry_run=false) override;
const GA_PrimitiveJSON *getJSON() const override;
/// Evalaute a point given a u,v coordinate (with derivatives)
GA_Offset result_vtx,
uint du, uint dv) const override;
/// Evalaute position given a u,v coordinate (with derivatives)
UT_Vector4 &pos,
float u, float v = 0,
unsigned du=0, unsigned dv=0) const override
{
return GEO_Primitive::evaluatePoint(pos, u, v,
du, dv);
}
/// @}
/// @{
/// Though not strictly required (i.e. not pure virtual), these methods
/// should be implemented for proper behaviour.
GEO_Primitive *copy(int preserve_shared_pts = 0) const override;
// Have we been deactivated and stashed?
void stashed(bool beingstashed,
GA_Offset offset=GA_INVALID_OFFSET) override;
/// @}
/// @{
/// Optional interface methods. Though not required, implementing these
/// will give better behaviour for the new primitive.
UT_Vector3 baryCenter() const override;
fpreal calcVolume(const UT_Vector3 &refpt) const override;
fpreal calcArea() const override;
fpreal calcPerimeter() const override;
/// @}
/// Load the order from a JSON value
bool loadOrder(const UT_JSONValue &p);
/// @{
/// Save/Load vertex list to a JSON stream
const GA_SaveMap &map) const;
const GA_LoadMap &map);
/// @}
/// Finds where the specified vertex offset is in this primitive's
/// vertex list.
{
for (GA_Size i = 0; i < 4; i++)
{
if (getVertexOffset(i) == vtxoff)
return i;
}
return -1;
}
/// Finds where in this primitive's vertex list, some vertex
/// is wired to the specified point offset.
{
for (GA_Size i = 0; i < 4; i++)
{
if (getPointOffset(i) == ptoff)
return i;
}
return -1;
}
/// Report approximate memory usage.
int64 getMemoryUsage() const override;
/// Count memory usage using a UT_MemoryCounter in order to count
/// shared memory correctly.
/// NOTE: This should always include sizeof(*this).
void countMemory(UT_MemoryCounter &counter) const override;
/// Allows you to find out what this primitive type was named.
static const GA_PrimitiveTypeId &theTypeId() { return theDefinition->getId(); }
/// Must be invoked during the factory callback to add us to the
/// list of primitives
static void registerMyself(GA_PrimitiveFactory *factory);
const GA_PrimitiveDefinition &getTypeDef() const override
{ return *theDefinition; }
/// @{
/// Conversion functions
GA_PointGroup *usedpts = 0) override;
/// @}
/// Optional build function
static GEO_PrimTetra *build(GA_Detail *gdp, bool appendpts = true);
/// Builds tetrahedrons using the specified range of point offsets,
/// as dictated by ntets and tetpointnumbers, in parallel.
/// tetpointnumbers lists the *offsets* of the points used by
/// each tetrahedron *MINUS* startpt, i.e. they are offsets relative to
/// startpt, *not* indices relative to startpt. The offset of the first
/// tetrahedron is returned, and the rest are at consecutive offsets. All
/// tetpointnumbers must be between 0 (inclusive) and npoints (exclusive).
///
/// NOTE: Existing primitives *are* allowed to be using the points in
/// the specified range already, and the tetrahedrons being created do not
/// do not need to use all of the points in the range. However,
/// these cases may impact performance.
static GA_Offset buildBlock(GA_Detail *detail,
const GA_Offset startpt,
const GA_Size npoints,
const GA_Size ntets,
const int *tetpointnumbers);
void normal(NormalComp &output) const override;
void normal(NormalCompD &output) const override;
int intersectRay(const UT_Vector3 &o, const UT_Vector3 &d,
float tmax = 1E17F, float tol = 1E-12F,
float *distance = 0, UT_Vector3 *pos = 0,
UT_Vector3 *nml = 0, int accurate = 0,
float *u = 0, float *v = 0,
int ignoretrim = 1) const override;
// NOTE: This functor class must be in the scope of GEO_PrimTetra
// so that it can access myVertexList.
// It has to be public so that UTparallelForLightItems
// can be instantiated for GCC with it.
class geo_SetVertexListsParallel
{
public:
const GA_Offset startvtx)
: myPrimitiveList(detail->getPrimitiveList())
, myStartPrim(startprim)
, myStartVtx(startvtx)
{}
{
char bcnt = 0;
GA_Offset vtxoff = myStartVtx + 4*r.begin();
for (GA_Size i = r.begin(); i != r.end(); ++i)
{
if (!bcnt++ && boss->opInterrupt())
break;
GA_Offset offset = myStartPrim + i;
GEO_PrimTetra *tet = (GEO_PrimTetra *)myPrimitiveList.get(offset);
tet->myVertexList.setTrivial(vtxoff, 4);
vtxoff += 4;
}
}
private:
GA_PrimitiveList &myPrimitiveList;
const GA_Offset myStartPrim;
const GA_Offset myStartVtx;
};
protected:
/// Declare methods for implementing intrinsic attributes.
void createVertices() const;
private:
static GA_PrimitiveDefinition *theDefinition;
};
}
#endif