#include "GU_PrimTetra.h"
#include <GA/GA_GBAttributeMath.h>
#include <GEO/GEO_AttributeHandleList.h>
#include <GEO/GEO_WorkVertexBuffer.h>
#include <GU/GU_PrimPoly.h>
#include <GU/GU_ConvertParms.h>
#include <GU/GU_RayIntersect.h>
#include "GT_PrimTetra.h"
using namespace HDK_Sample;
GA_PrimitiveDefinition *GU_PrimTetra::theDef = 0;
GU_PrimTetra *
GU_PrimTetra::build(GU_Detail *gdp, int appendPoints)
{
GU_PrimTetra *tet;
int npts;
tet = (GU_PrimTetra *)gdp->appendPrimitive(GU_PrimTetra::theTypeId());
npts = tet->getVertexCount();
if (appendPoints)
{
GEO_Primitive *prim = tet;
for (int i = 0; i < npts; i++)
{
prim->getVertexElement(i).setPointOffset(gdp->appendPointOffset());
}
}
return tet;
}
GU_PrimTetra::~GU_PrimTetra()
{
}
static GA_Primitive *
gu_newPrimTetra(GA_Detail &detail, GA_Offset offset)
{
return new GU_PrimTetra(static_cast<GU_Detail *>(&detail), offset);
}
void
GU_PrimTetra::registerMyself(GA_PrimitiveFactory *factory)
{
if (theDef)
return;
theDef = factory->registerDefinition("HDK_Tetrahedron",
gu_newPrimTetra,
GA_FAMILY_NONE);
theDef->setLabel("hdk_tetrahedron");
registerIntrinsics(*theDef);
GT_PrimTetraCollect::registerPrimitive(theDef->getId());
}
int64
GU_PrimTetra::getMemoryUsage() const
{
exint mem = sizeof(*this);
return mem;
}
static GEO_Primitive *
gu_buildPoly(GU_PrimTetra *tet, GU_Detail *gdp, int v1, int v2, int v3,
bool preserveGroups)
{
GU_PrimPoly *poly;
poly = GU_PrimPoly::build(gdp, 3, 0, 0);
poly->copyAttributesAndGroups(*tet, preserveGroups);
gdp->copyVertex((*poly)(0), tet->getVertexElement(v1), 1);
gdp->copyVertex((*poly)(1), tet->getVertexElement(v2), 1);
gdp->copyVertex((*poly)(2), tet->getVertexElement(v3), 1);
return poly;
}
GEO_Primitive *
GU_PrimTetra::convertNew(GU_ConvertParms &parms)
{
GEO_Primitive *prim = 0;
GU_Detail *gdp = (GU_Detail *)getParent();
if (parms.toType == GEO_PrimTypeCompat::GEOPRIMPOLY)
{
gu_buildPoly(this, gdp, 0, 1, 2, parms.preserveGroups);
gu_buildPoly(this, gdp, 1, 3, 2, parms.preserveGroups);
gu_buildPoly(this, gdp, 1, 0, 3, parms.preserveGroups);
prim = gu_buildPoly(this, gdp, 0, 2, 3, parms.preserveGroups);
}
return prim;
}
GEO_Primitive *
GU_PrimTetra::convert(GU_ConvertParms &parms, GA_PointGroup *usedpts)
{
GEO_Primitive *prim = convertNew(parms);
GEO_Detail *gdp = getParent();
GA_PrimitiveGroup *group;
if (prim)
{
if (usedpts) addPointRefToGroup(*usedpts);
if (group = parms.getDeletePrimitives())
group->add(this);
else gdp->deletePrimitive(*this, !usedpts);
}
return prim;
}
void
GU_PrimTetra::normal(NormalComp &output) const
{
}
void *
GU_PrimTetra::castTo() const
{
return (GU_Primitive *)this;
}
const GEO_Primitive *
GU_PrimTetra::castToGeo(void) const
{
return this;
}
GU_RayIntersect *
GU_PrimTetra::createRayCache(int &persistent)
{
GU_Detail *gdp = (GU_Detail *)getParent();
GU_RayIntersect *intersect;
persistent = 0;
if (gdp->cacheable())
buildRayCache();
intersect = getRayCache();
if (!intersect)
{
intersect = new GU_RayIntersect(gdp, this);
persistent = 1;
}
return intersect;
}
int
GU_PrimTetra::intersectRay(const UT_Vector3 &org, const UT_Vector3 &dir,
float tmax, float , float *distance,
UT_Vector3 *pos, UT_Vector3 *nml,
int, float *, float *, int) const
{
int result;
float dist;
UT_BoundingBox bbox;
getBBox(&bbox);
result = bbox.intersectRay(org, dir, tmax, &dist, nml);
if (result)
{
if (distance) *distance = dist;
if (pos) *pos = org + dist * dir;
}
return result;
}
extern "C" {
void
newGeometryPrim(GA_PrimitiveFactory *factory)
{
GU_PrimTetra::registerMyself(factory);
}
}