aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/common/src/CurveImpl.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/common/src/CurveImpl.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'APEX_1.4/common/src/CurveImpl.cpp')
-rw-r--r--APEX_1.4/common/src/CurveImpl.cpp182
1 files changed, 182 insertions, 0 deletions
diff --git a/APEX_1.4/common/src/CurveImpl.cpp b/APEX_1.4/common/src/CurveImpl.cpp
new file mode 100644
index 00000000..c2daba5c
--- /dev/null
+++ b/APEX_1.4/common/src/CurveImpl.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
+ *
+ * NVIDIA CORPORATION and its licensors retain all intellectual property
+ * and proprietary rights in and to this software, related documentation
+ * and any modifications thereto. Any use, reproduction, disclosure or
+ * distribution of this software and related documentation without an express
+ * license agreement from NVIDIA CORPORATION is strictly prohibited.
+ */
+
+
+#include "Apex.h"
+#include "PxAssert.h"
+#include "nvparameterized/NvParameterized.h"
+#include "Curve.h"
+#include "CurveImpl.h"
+
+namespace nvidia
+{
+namespace apex
+{
+
+/**
+ Linear interpolation. "in" and "out" stands here for X and Y coordinates of the control points
+*/
+inline float lerp(float inCurrent, float inMin, float inMax, float outMin, float outMax)
+{
+ if (inMin == inMax)
+ {
+ return outMin;
+ }
+
+ return ((inCurrent - inMin) / (inMax - inMin)) * (outMax - outMin) + outMin;
+}
+
+/**
+ The CurveImpl is a class for storing control points on a curve and evaluating the results later.
+*/
+
+/**
+ Retrieve the output Y for the specified input x, based on the properties of the stored curve described
+ by mControlPoints.
+*/
+float CurveImpl::evaluate(float x) const
+{
+ Vec2R xPoints, yPoints;
+ if (calculateControlPoints(x, xPoints, yPoints))
+ {
+ return lerp(x, xPoints[0], xPoints[1], yPoints[0], yPoints[1]);
+ }
+ else if (mControlPoints.size() == 1)
+ {
+ return mControlPoints[0].y;
+ }
+ else
+ {
+ // This is too noisy for editors...
+ //PX_ASSERT(!"Unable to find control points that contained the specified curve parameter");
+ return 0;
+ }
+}
+
+/**
+ Add a control point to the list of control points, returning the index of the new point.
+*/
+uint32_t CurveImpl::addControlPoint(const Vec2R& controlPoint)
+{
+ uint32_t index = calculateFollowingControlPoint(controlPoint.x);
+
+ if (index == mControlPoints.size())
+ {
+ // add element to the end
+ Vec2R& v2 = mControlPoints.insert();
+ v2 = controlPoint;
+ }
+ else
+ {
+ // memmove all elements from index - end to index+1 - new_end
+ uint32_t oldSize = mControlPoints.size();
+ mControlPoints.insert();
+ memmove(&mControlPoints[index + 1], &mControlPoints[index], sizeof(Vec2R) * (oldSize - index));
+ mControlPoints[index] = controlPoint;
+ }
+ return index;
+}
+
+/**
+ Add a control points to the list of control points. Assuming the
+ hPoints points to a list of vec2s
+*/
+void CurveImpl::addControlPoints(::NvParameterized::Interface* param, ::NvParameterized::Handle& hPoints)
+{
+ ::NvParameterized::Handle ih(*param), hMember(*param);
+ int arraySize = 0;
+ PX_ASSERT(hPoints.getConstInterface() == param);
+ hPoints.getArraySize(arraySize);
+ for (int i = 0; i < arraySize; i++)
+ {
+ hPoints.getChildHandle(i, ih);
+ Vec2R tmpVec2;
+ ih.getChildHandle(0, hMember);
+ hMember.getParamF32(tmpVec2.x);
+ ih.getChildHandle(1, hMember);
+ hMember.getParamF32(tmpVec2.y);
+
+ addControlPoint(tmpVec2);
+ }
+}
+
+/**
+ Locates the control points that contain x, placing the resulting control points in the two
+ out parameters. Returns true if the points were found, false otherwise. If the points were not
+ found, the output variables are untouched
+*/
+bool CurveImpl::calculateControlPoints(float x, Vec2R& outXPoints, Vec2R& outYPoints) const
+{
+ uint32_t controlPointSize = mControlPoints.size();
+ if (controlPointSize < 2)
+ {
+ return false;
+ }
+
+ uint32_t followControlPoint = calculateFollowingControlPoint(x);
+ if (followControlPoint == 0)
+ {
+ outXPoints[0] = outXPoints[1] = mControlPoints[0].x;
+ outYPoints[0] = outYPoints[1] = mControlPoints[0].y;
+ return true;
+ }
+ else if (followControlPoint == controlPointSize)
+ {
+ outXPoints[0] = outXPoints[1] = mControlPoints[followControlPoint - 1].x;
+ outYPoints[0] = outYPoints[1] = mControlPoints[followControlPoint - 1].y;
+ return true;
+ }
+
+ outXPoints[0] = mControlPoints[followControlPoint - 1].x;
+ outXPoints[1] = mControlPoints[followControlPoint].x;
+
+ outYPoints[0] = mControlPoints[followControlPoint - 1].y;
+ outYPoints[1] = mControlPoints[followControlPoint].y;
+
+ return true;
+}
+
+/**
+ Locates the first control point with x larger than xValue or the nimber of control points if such point doesn't exist
+*/
+uint32_t CurveImpl::calculateFollowingControlPoint(float xValue) const
+{
+ // TODO: This could be made O(log(N)), but I think there should
+ // be so few entries that it's not worth the code complexity.
+ uint32_t cpSize = mControlPoints.size();
+
+ for (uint32_t u = 0; u < cpSize; ++u)
+ {
+ if (xValue <= mControlPoints[u].x)
+ {
+ return u;
+ }
+ }
+
+ return cpSize;
+}
+
+///get the array of control points
+const Vec2R* CurveImpl::getControlPoints(uint32_t& outCount) const
+{
+ outCount = mControlPoints.size();
+ if (outCount)
+ {
+ return &mControlPoints.front();
+ }
+ else
+ {
+ // LRR: there's more to this, chase this down later
+ return NULL;
+ }
+}
+
+}
+} // namespace nvidia::apex