///////////////////////////////////////////////////////////// // CINEMA 4D SDK // ///////////////////////////////////////////////////////////// // (c) 1989-2006 MAXON Computer GmbH, all rights reserved // ///////////////////////////////////////////////////////////// //--------------------------------------------------- //Spline Helper Class //Routines to generate a full set of spline matrices //incorporating a correct normal //and accurate spline length to realworld length controls //--------------------------------------------------- #include "lib_splinehelp.h" SplineHelpLibrary* splinehelplib_cache; static SplineHelpLibrary* CheckSplineHelpLib(Int32 offset) { return (SplineHelpLibrary*)CheckLib(C4D_SPLINEHELP_LIBRARY_ID, offset, (C4DLibrary**)&splinehelplib_cache); } SplineHelp *SplineHelp::Alloc(void) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, Alloc)); if (!shlib || !shlib->Alloc) return nullptr; return (SplineHelp*)shlib->Alloc(); } void SplineHelp::Free(SplineHelp *&node) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, Free)); if (!shlib || !shlib->Free) return; iSplineHelp *tmp = (iSplineHelp*)node; shlib->Free(tmp); node=nullptr; } //------------------------- //Always call this to begin with before calling any other functions //AutoAllocsh; FreeSpline will be called automatically //sh->InitSpline(myspline); //... do stuff ... Bool SplineHelp::InitSpline(BaseObject *op,Vector upvector, BaseObject *rail, Bool target_rail, Bool use_deformed_points, Bool force_update, Bool use_global_space) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, InitSpline)); if (!shlib || !shlib->InitSpline) return false; return (((iSplineHelp*)this)->*(shlib->InitSpline))(op, upvector,rail, target_rail, use_deformed_points, force_update, use_global_space); } //must be called afterwards to free data void SplineHelp::FreeSpline(void) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, FreeSpline)); if (!shlib || !shlib->FreeSpline) return; (((iSplineHelp*)this)->*(shlib->FreeSpline))(); } //----------------------------------------------------- //helper routines //Have we been inited properly? Bool SplineHelp::Exists(void) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, Exists)); if (!shlib || !shlib->Exists) return false; return (((iSplineHelp*)this)->*(shlib->Exists))(); } //Retrieve splines segment count Int32 SplineHelp::GetSegmentCount(void) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetSegmentCount)); if (!shlib || !shlib->GetSegmentCount) return 0; return (((iSplineHelp*)this)->*(shlib->GetSegmentCount))(); } //Get the total length of the spline Float SplineHelp::GetSplineLength(void) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetSplineLength)); if (!shlib || !shlib->GetSplineLength) return 0.0; return (((iSplineHelp*)this)->*(shlib->GetSplineLength))(); } //Get the length of a single segment Float SplineHelp::GetSegmentLength(Int32 segment) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetSegmentLength)); if (!shlib || !shlib->GetSegmentLength) return 0.0; return (((iSplineHelp*)this)->*(shlib->GetSegmentLength))(segment); } //Get the length of a single segment Matrix SplineHelp::GetVertexMatrix(Int32 index) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetVertexMatrix)); if (!shlib || !shlib->GetVertexMatrix) return Matrix(); return (((iSplineHelp*)this)->*(shlib->GetVertexMatrix))(index); } //Get the real value along the segment Float SplineHelp::GetPointValue(Float offset, Int32 segment) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetPointValue)); if (!shlib || !shlib->GetPointValue) return 0.0; return (((iSplineHelp*)this)->*(shlib->GetPointValue))(offset,segment); } //Retrieve the nearest points index from the lineobject Int32 SplineHelp::GetPointIndex(Float offset, Int32 segment) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetPointIndex)); if (!shlib || !shlib->GetPointIndex) return 0; return (((iSplineHelp*)this)->*(shlib->GetPointIndex))(offset,segment); } //Return the position at offset in global coordinates Vector SplineHelp::GetPosition(Float offset, Int32 segment, Bool smooth, Bool realoffset) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetPosition)); if (!shlib || !shlib->GetPosition) return Vector(); return (((iSplineHelp*)this)->*(shlib->GetPosition))(offset,segment,smooth, realoffset); } //Get the size of the vertex (distance to the rail) if using a rail spline Float SplineHelp::GetSize(Float offset, Int32 segment, Bool smooth, Bool realoffset) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetSize)); if (!shlib || !shlib->GetSize) return 1.0; return (((iSplineHelp*)this)->*(shlib->GetSize))(offset,segment,smooth, realoffset); } //Get the size of the vertex (distance to the rail) if using a rail spline Float SplineHelp::GetVertexSize(Int32 index) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetVertexSize)); if (!shlib || !shlib->GetVertexSize) return 1.0; return (((iSplineHelp*)this)->*(shlib->GetVertexSize))(index); } //Returns the Tangent at offset in global coordinates Vector SplineHelp::GetTangent(Float offset, Int32 segment, Bool smooth, Bool realoffset) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetTangent)); if (!shlib || !shlib->GetTangent) return Vector(); return (((iSplineHelp*)this)->*(shlib->GetTangent))(offset,segment,smooth, realoffset); } //Returns the Normal at offset in global coordinates Vector SplineHelp::GetNormal(Float offset, Int32 segment, Bool smooth, Bool realoffset) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetNormal)); if (!shlib || !shlib->GetNormal) return Vector(); return (((iSplineHelp*)this)->*(shlib->GetNormal))(offset,segment,smooth, realoffset); } //Returns the CrossNormal at offset in global coordinates Vector SplineHelp::GetCrossNormal(Float offset, Int32 segment, Bool smooth, Bool realoffset) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetCrossNormal)); if (!shlib || !shlib->GetCrossNormal) return Vector(); return (((iSplineHelp*)this)->*(shlib->GetCrossNormal))(offset,segment,smooth, realoffset); } //Calculates the offset using a real world unit length Float SplineHelp::GetOffsetFromUnit(Float unitoffset, Int32 segment) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetOffsetFromUnit)); if (!shlib || !shlib->GetOffsetFromUnit) return 0.0; return (((iSplineHelp*)this)->*(shlib->GetOffsetFromUnit))(unitoffset,segment); } //Converts offset in % of points to offset in %of length Float SplineHelp::GetOffsetFromReal(Float offset, Int32 segment) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetOffsetFromReal)); if (!shlib || !shlib->GetOffsetFromReal) return 0.0; return (((iSplineHelp*)this)->*(shlib->GetOffsetFromReal))(offset,segment); } //Retrives a matrix for any point along the spline in world space Matrix SplineHelp::GetMatrix(Float offset, Int32 segment, Bool smooth, Bool realoffset) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetMatrix)); if (!shlib || !shlib->GetMatrix) return Matrix(); return (((iSplineHelp*)this)->*(shlib->GetMatrix))(offset,segment,smooth,realoffset); } //retrieves an offset, index and segment from a line objects point index, users own offset,ind and segment void SplineHelp::GetLinePointSegment(Int32 index, Float *offset, Int32 *ind, Int32 *segment) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetLinePointSegment)); if (!shlib || !shlib->GetLinePointSegment) return; (((iSplineHelp*)this)->*(shlib->GetLinePointSegment))(index,offset,ind,segment); } //retrieves an offse, index and segment from a spline objects point index, users own offset,ind and segment void SplineHelp::GetSplinePointSegment(Int32 index, Float *offset, Int32 *ind, Int32 *segment) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetSplinePointSegment)); if (!shlib || !shlib->GetSplinePointSegment) return; (((iSplineHelp*)this)->*(shlib->GetSplinePointSegment))(index,offset,ind,segment); } //converts an offset in percent over the whole spline length to a real offset, and segment (user owns off and segment) //realoffset determines if the space used is unit space, or point index space void SplineHelp::GlobalToLocal(Float offset, Float *off, Int32 *segment, Bool realoffset) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GlobalToLocal)); if (!shlib || !shlib->GlobalToLocal) return; (((iSplineHelp*)this)->*(shlib->GlobalToLocal))(offset,off,segment,realoffset); } //Converts the splines vertex index to a comparable line object index (used in the splinehelp), returns NOTOK if out of bounds Int32 SplineHelp::SplineToLineIndex(Int32 index) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, SplineToLineIndex)); if (!shlib || !shlib->SplineToLineIndex) return NOTOK; return (((iSplineHelp*)this)->*(shlib->SplineToLineIndex))(index); } //Gets the number of lineobject points in the passed spline, optionally just in a single segment, returns NOTOK if out of bounds Int32 SplineHelp::GetVertexCount(Int32 segment /*= NOTOK*/) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetVertexCount)); if (!shlib || !shlib->GetVertexCount) return NOTOK; return (((iSplineHelp*)this)->*(shlib->GetVertexCount))(segment); } //Gets the number of lineobject points in the passed spline, optionally just in a single segment Matrix SplineHelp::GetVertexMatrix(Int32 segment, Int32 index) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetVertexMatrix2)); if (!shlib || !shlib->GetVertexMatrix2) return Matrix(); return (((iSplineHelp*)this)->*(shlib->GetVertexMatrix2))(segment, index); } Bool SplineHelp::IsClosed(Int32 segment) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, IsClosed)); if (!shlib || !shlib->IsClosed) return false; return (((iSplineHelp*)this)->*(shlib->IsClosed))(segment); } SPLINETYPE SplineHelp::GetType(void) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetType)); if (!shlib || !shlib->GetType) return SPLINETYPE_LINEAR; return (((iSplineHelp*)this)->*(shlib->GetType))(); } Bool SplineHelp::CopyTo(SplineHelp *dest) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, CopyTo)); if (!shlib || !shlib->CopyTo) return false; iSplineHelp *d = (iSplineHelp*)dest; if (!d) return false; return (((iSplineHelp*)this)->*(shlib->CopyTo))(d); } //Retrieve spline original point (vertex) count rather than the line point count Int32 SplineHelp::GetPointCount(void) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, GetPointCount)); if (!shlib || !shlib->GetPointCount) return 0; return (((iSplineHelp*)this)->*(shlib->GetPointCount))(); } void SplineHelp::SetOwner(BaseObject *op) { SplineHelpLibrary *shlib = CheckSplineHelpLib(LIBOFFSET(SplineHelpLibrary, SetOwner)); if (!shlib || !shlib->SetOwner) return; return (((iSplineHelp*)this)->*(shlib->SetOwner))(op); }