0

I have a bezier curve class. Each point on the curve is defined thus:

struct bpoint
{
    vector3D position;
    vector3D controlpoint_in;
    vector3d controlpoint_out;
};

To retrieve a point on the curve's spline (the curve can have infinite points), I use this function:

vector3d GetSplinePoint(float thePos)
{
   float aPos=thePos-floorf(thePos);
   int aIPos=(int)floorf(thePos);

   bpoint& aP1=pointList[aIPos];
   bpoint& aP2=pointList[min(aIPos+1,pointList.size())];

    vector3D aResult;
    vector3D aAB, aBC, aCD, aABBC, aBCCD;
    Lerp(aAB,aP1.mPos,aP1.mOut,aPos);
    Lerp(aBC,aP1.mOut,aP2.mIn,aPos);
    Lerp(aCD,aP2.mIn,aP2.mPos,aPos);
    Lerp(aABBC,aAB,aBC,aPos);
    Lerp(aBCCD,aBC,aCD,aPos);
    Lerp(aResult,aABBC,aBCCD,aPos);
    return aResult;
}

Works great, but now I'm in a situation where I want to add normals to each point, so that I can do some fancier stuff (rotations, etc). Like so:

struct bpoint
{
    vector3D position;
    vector3D controlpoint_in;
    vector3d controlpoint_out;
    vector3d normal;
};

I've been utterly unsuccessful in trying to write a GetSplineNormal(float thePos) function. I'm not even sure where to begin-- I thought I could just interpolate between the points, but I don't know how to factor in the control points.

How could I accomplish this?

KiraHoneybee
  • 495
  • 3
  • 12
  • 1
    Does this answer your question? [Getting consistent normals from a 3D cubic bezier path](https://stackoverflow.com/questions/25453159/getting-consistent-normals-from-a-3d-cubic-bezier-path) – Mike 'Pomax' Kamermans Jan 13 '22 at 03:51
  • switch to polynomial form ... then just do 1st derivate by parameter and the result is tangent (normal of plane in which all the normals are). however in 3D you need another reference vector to align the normal !!! in case you are dealing with surfaces then do 2 partial derivates one for each parameter and their cross product is your normal ... – Spektre Jan 13 '22 at 09:09

1 Answers1

1

Ok, so, there are a few things to consider, mathematically speaking.

First, your curve has a certain shape, so at each point of the curve there is one and only one plane perpendicular to the current direction of the curve. The normal has to be a part of this plane.

So your curve is parametrized by thePos, which, to simplyfy my mathemathical notation, I will write as t: x(t), y(t), z(t). The perpendicular plane at pos t is given by the equation:

d_t x(t) * (x - x(t)) + d_t y(t) * (y - y(t)) + d_t z(t) * (z - z(t)) = 0,

where d_t x(t) is the derivative with respect to t of x(t), d_t y(t) for y(t) and d_t z(t) for z(t).

For the orientation of the normal vector (i.e. in which direction the normal is facing in this perpendicular plane), you can interpolate between the two control points. Just pay attention, interpolating angles can be tricky, as you have to account for the direction. Linear interpolation of the angle coordinate is an option, but you can also interpolate the normal vectors directly and then reproject on the perpendicular plane using least squares. It really depends what you want to use the normal for.

Finally, remember that this perpendicular plane also exists at the control points, so you might have to constrain the normal given by the user (by reprojecting it using least squares).

Laurent Jospin
  • 604
  • 5
  • 9
  • "The normal has to be a part of this plane" it does not. That's a _convenient_ normal, not it's not "the" normal. _Any_ vector at a right angle to the tangent is mathematically valid normal, and there are infinitely many. – Mike 'Pomax' Kamermans Jan 13 '22 at 03:53
  • 1
    Yes, but the plane equation given in the answer is the set of all vectors forming a right angle with the tangent, so both your definition and mine are equivalent. The only free parameter is the orientation of the normal in the perpendicular plane. – Laurent Jospin Jan 13 '22 at 04:11
  • (assuming the current point considered in the curve is the origin of a local coordinate system with the same orientation as the global system) – Laurent Jospin Jan 13 '22 at 04:22
  • yeah, that's fair enough. – Mike 'Pomax' Kamermans Jan 13 '22 at 04:57