In my project I need a curve to follow.
I created a bezier curve in blend file. But I found that the gkCurve
don't support bezier curve. So I do a little work to make class
gkCurve to support bezier.
First, in gkCurveProperties of
gkSerialize.h:
class gkCurveProperties
{
public:
enum CurveType
{
CU_Bezier,
CU_Spline,
CU_Points
};
public:
gkCurveProperties()
:m_type(CU_Points), m_isCyclic(false)
{
}
CurveType m_type;
utArray<gkVector3> m_points;
typedef utArray<utArray<gkVector3>
> BezTriples;
BezTriples m_BezTriples;
bool m_isCyclic;
};
Second, in function
gkBlenderSceneConverter::convertObjectCurve of
gkBlenderSceneConverter:
void
gkBlenderSceneConverter::convertObjectCurve(gkGameObject* gobj,
Blender::Object* bobj)
{
GK_ASSERT(gobj->getType() ==
GK_CURVE && bobj->data);
gkCurve* obj =
static_cast<gkCurve*>(gobj);
gkCurveProperties& props =
obj->getCurveProperties();
Blender::Curve* curve =
static_cast<Blender::Curve*>(bobj->data);
Blender::Nurb* nurb = (Blender::Nurb*
)curve->nurb.first;
// if (nurb->type != CU_NURBS) {
// gkLogger::write("Only
Nurb-Curves are supported, atm! ("+obj->getName()+")");
// return;
// }
props.m_isCyclic = (nurb->flagu &
CU_CYCLIC) || (nurb->flagv & CU_CYCLIC);
switch (nurb->type)
{
case CU_NURBS:
{
for (int i=0;i<nurb->pntsu;i++){
short int nurbType = nurb->type;
const Blender::BPoint& pnt =
nurb->bp[i];
// TODO: check if these are
converted properly
gkVector3
point(pnt.vec[0],pnt.vec[1],pnt.vec[2]);
props.m_points.push_back(point);
}
break;
}
case CU_BEZIER:
{
for (int i = 0; i <
nurb->pntsu; i++)
{
const Blender::BezTriple&
trp = nurb->bezt[i];
utArray<gkVector3>
bezTriple;
for (int j = 0; j < 3; j++)
{
gkVector3 bt;
bt.x = trp.vec[j][0];
bt.y = trp.vec[j][1];
bt.z = trp.vec[j][2];
bezTriple.push_back(bt);
printf("%f %f %f ",
bt.x, bt.y, bt.z);
}
props.m_BezTriples.push_back(bezTriple);
}
printf("\n");
props.m_type =
gkCurveProperties::CU_Bezier;
break;
}
default:
gkLogger::write("Only
Nurb-Curves and Bezier-Curves are supported, atm!
("+obj->getName()+")");
return;
}
}
Third, in gkCurve.h:
private:
gkGameObject* clone(const gkString&
name);
void makeBezier(gkScalar _t,
utArray<gkVector3>& _first, utArray<gkVector3>&
_second);
gkCurveProperties m_curveProps;
virtual void createInstanceImpl(void);
virtual void
destroyInstanceImpl(void);
utArray<gkVector3>
m_bezierPoints;
Fourth, in
gkCurve.cpp I rewiter the follow functions:
const gkVector3
gkCurve::getPoint(int nr)
{
switch
(m_curveProps.m_type)
{
case
gkCurveProperties::CU_Points:
{
if (nr <
(int)m_curveProps.m_points.size()) {
return
getWorldTransform() * m_curveProps.m_points.at(nr);
}
else
{
// TODO:
better error handling
return
gkVector3::ZERO;
}
}
case
gkCurveProperties::CU_Bezier:
{
if (nr <
(int)m_bezierPoints.size()) {
return
getWorldTransform() * m_bezierPoints.at(nr);
}
else
{
// TODO:
better error handling
return
gkVector3::ZERO;
}
}
}
}
int
gkCurve::getPointCount()
{
switch
(m_curveProps.m_type)
{
case
gkCurveProperties::CU_Points:
return
m_curveProps.m_points.size();
case
gkCurveProperties::CU_Bezier:
return
m_bezierPoints.size();
}
}
void
gkCurve::generateBezierPoints(gkScalar _t)
{
m_bezierPoints.clear();
UTsize triCount =
m_curveProps.m_BezTriples.size();
for (UTsize i =
0; i < triCount - 1; i++)
{
utArray<gkVector3>&
bezFirst = m_curveProps.m_BezTriples.at(i);
utArray<gkVector3>&
bezSecond = m_curveProps.m_BezTriples.at(i + 1);
makeBezier(_t,
bezFirst, bezSecond);
}
if
(m_curveProps.m_isCyclic)
{
utArray<gkVector3>&
bezFirst = m_curveProps.m_BezTriples.at(triCount - 1);
utArray<gkVector3>&
bezSecond = m_curveProps.m_BezTriples.at(0);
makeBezier(_t,
bezFirst, bezSecond);
}
}
void
gkCurve::makeBezier(gkScalar _t, utArray< gkVector3 >&
_first, utArray< gkVector3 >& _second)
{
gkVector3&
pt0 = _first.at(1);
gkVector3&
pt1 = _first.at(2);
gkVector3&
pt2 = _second.at(0);
gkVector3&
pt3 = _second.at(1);
for (gkScalar t =
0.f; t < 1.f; t += _t)
{
gkScalar yt = 1
- t;
gkScalar t1 = yt
* yt;
gkScalar t2 = 3
* yt * t;
gkVector3 pt =
pt0 * t1 * yt + pt1 * t2 * yt + pt2 * t2 * t + pt3 * t * t * t;
m_bezierPoints.push_back(pt);
}
}
void
gkCurve::showDebug()
{
if (m_scene)
{
gkDebugger*
debug = m_scene->getDebugger();
if (!debug)
{
return;
}
unsigned int n =
getPointCount();
if (n)
{
static const
gkVector3 RED_COLOR(0.8f, 0.5f, 0);
gkVector3
oldPoint = getPoint(0);
for (unsigned
int i = 1; i < n; i++)
{
gkVector3
point = getPoint(i);
debug->drawLine(
oldPoint,
point,
RED_COLOR
);
oldPoint =
point;
}
}
}
}
In my code. I just
use gkCurve like:
gkCurve*
m_pathCurve = m_scene->getObject("PATH_CURVE”)->getCurve();
m_pathCurve->generateBezierPoints(0.05f);
Then you can use
m_pathCurve->getPointCount() and m_pathCurve->getPoint(n) to
manipulate the bezier.
Follow is a
snapshot of blend file:
Follow is a
snapshot of program:
没有评论:
发表评论