mirror of
https://github.com/love2d/love.git
synced 2026-08-18 03:34:23 +02:00
Merged in muddmaker/love-render-curve-segment (pull request #39)
Add BezierCurve:renderSegment
This commit is contained in:
+2
-1
@@ -28,6 +28,7 @@ Released: N/A
|
|||||||
* Added Text objects and love.graphics.newText.
|
* Added Text objects and love.graphics.newText.
|
||||||
* Added BMFont bitmap font file support to love.graphics.newFont and love.font.
|
* Added BMFont bitmap font file support to love.graphics.newFont and love.font.
|
||||||
* Added love.window.maximize.
|
* Added love.window.maximize.
|
||||||
|
* Added BezierCurve:renderSegment and BezierCurve:removePoint.
|
||||||
|
|
||||||
* Removed love.filesystem.exists (use love.filesystem.isFile or love.filesystem.isDirectory instead.)
|
* Removed love.filesystem.exists (use love.filesystem.isFile or love.filesystem.isDirectory instead.)
|
||||||
* Removed the "wu" and "wd" constants for love.mousepressed (replaced by love.wheelmoved.)
|
* Removed the "wu" and "wd" constants for love.mousepressed (replaced by love.wheelmoved.)
|
||||||
@@ -315,7 +316,7 @@ LOVE 0.9.0 [Baby Inspector]
|
|||||||
* Added love.window.getIcon.
|
* Added love.window.getIcon.
|
||||||
* Added t.window.icon to love.conf.
|
* Added t.window.icon to love.conf.
|
||||||
* Added love.mousefocus and love.window.hasMouseFocus.
|
* Added love.mousefocus and love.window.hasMouseFocus.
|
||||||
* Added custom hardware cursors via love.mouse.newCursor.
|
* Added custom hardware cursors via love.mouse.newCursor.
|
||||||
* Added love.mouse.setX/setY.
|
* Added love.mouse.setX/setY.
|
||||||
* Added Joystick objects.
|
* Added Joystick objects.
|
||||||
* Added love.joystick.getJoystick.
|
* Added love.joystick.getJoystick.
|
||||||
|
|||||||
@@ -104,35 +104,46 @@ BezierCurve BezierCurve::getDerivative() const
|
|||||||
|
|
||||||
const Vector &BezierCurve::getControlPoint(int i) const
|
const Vector &BezierCurve::getControlPoint(int i) const
|
||||||
{
|
{
|
||||||
if (i < 0)
|
while (i < 0)
|
||||||
i += controlPoints.size();
|
i += controlPoints.size();
|
||||||
|
|
||||||
if (i < 0 || (size_t) i >= controlPoints.size())
|
while ((size_t) i >= controlPoints.size())
|
||||||
throw Exception("Invalid control point index");
|
i -= controlPoints.size();
|
||||||
|
|
||||||
return controlPoints[i];
|
return controlPoints[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void BezierCurve::setControlPoint(int i, const Vector &point)
|
void BezierCurve::setControlPoint(int i, const Vector &point)
|
||||||
{
|
{
|
||||||
if (i < 0)
|
while (i < 0)
|
||||||
i += controlPoints.size();
|
i += controlPoints.size();
|
||||||
|
|
||||||
if (i < 0 || (size_t) i >= controlPoints.size())
|
while ((size_t) i >= controlPoints.size())
|
||||||
throw Exception("Invalid control point index");
|
i -= controlPoints.size();
|
||||||
|
|
||||||
controlPoints[i] = point;
|
controlPoints[i] = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BezierCurve::insertControlPoint(const Vector &point, int pos)
|
void BezierCurve::insertControlPoint(const Vector &point, int i)
|
||||||
{
|
{
|
||||||
if (pos < 0)
|
while (i < 0)
|
||||||
pos += controlPoints.size() + 1;
|
i += controlPoints.size();
|
||||||
|
|
||||||
if (pos < 0 ||(size_t) pos > controlPoints.size())
|
while ((size_t) i > controlPoints.size())
|
||||||
throw Exception("Invalid control point index");
|
i -= controlPoints.size();
|
||||||
|
|
||||||
controlPoints.insert(controlPoints.begin() + pos, point);
|
controlPoints.insert(controlPoints.begin() + i, point);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BezierCurve::removeControlPoint(int i)
|
||||||
|
{
|
||||||
|
while (i < 0)
|
||||||
|
i += controlPoints.size();
|
||||||
|
|
||||||
|
while ((size_t) i >= controlPoints.size())
|
||||||
|
i -= controlPoints.size();
|
||||||
|
|
||||||
|
controlPoints.erase(controlPoints.begin() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BezierCurve::translate(const Vector &t)
|
void BezierCurve::translate(const Vector &t)
|
||||||
@@ -170,7 +181,7 @@ Vector BezierCurve::evaluate(double t) const
|
|||||||
for (size_t step = 1; step < controlPoints.size(); ++step)
|
for (size_t step = 1; step < controlPoints.size(); ++step)
|
||||||
for (size_t i = 0; i < controlPoints.size() - step; ++i)
|
for (size_t i = 0; i < controlPoints.size() - step; ++i)
|
||||||
points[i] = points[i] * (1-t) + points[i+1] * t;
|
points[i] = points[i] * (1-t) + points[i+1] * t;
|
||||||
|
|
||||||
return points[0];
|
return points[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,6 +194,30 @@ vector<Vector> BezierCurve::render(int accuracy) const
|
|||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<Vector> BezierCurve::renderSegment(double start, double end, size_t accuracy) const
|
||||||
|
{
|
||||||
|
if (controlPoints.size() < 2)
|
||||||
|
throw Exception("Invalid Bezier curve: Not enough control points.");
|
||||||
|
vector<Vector> vertices(controlPoints);
|
||||||
|
subdivide(vertices, accuracy);
|
||||||
|
if (start == end)
|
||||||
|
{
|
||||||
|
vertices.clear();
|
||||||
|
}
|
||||||
|
else if (start < end)
|
||||||
|
{
|
||||||
|
size_t start_idx = size_t(start * vertices.size());
|
||||||
|
size_t end_idx = size_t(end * vertices.size() + 0.5);
|
||||||
|
return std::vector<Vector>(vertices.begin() + start_idx, vertices.begin() + end_idx);
|
||||||
|
}
|
||||||
|
else if (end > start)
|
||||||
|
{
|
||||||
|
size_t start_idx = size_t(end * vertices.size() + 0.5);
|
||||||
|
size_t end_idx = size_t(start * vertices.size());
|
||||||
|
return std::vector<Vector>(vertices.begin() + start_idx, vertices.begin() + end_idx);
|
||||||
|
}
|
||||||
|
return vertices;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace love
|
} // namespace love
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ public:
|
|||||||
**/
|
**/
|
||||||
void insertControlPoint(const Vector &point, int pos = -1);
|
void insertControlPoint(const Vector &point, int pos = -1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the i'th control point from the curve.
|
||||||
|
* @param i Control point to remove
|
||||||
|
**/
|
||||||
|
void removeControlPoint(int i);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns Number of control points.
|
* @returns Number of control points.
|
||||||
**/
|
**/
|
||||||
@@ -114,6 +120,15 @@ public:
|
|||||||
**/
|
**/
|
||||||
std::vector<Vector> render(int accuracy = 4) const;
|
std::vector<Vector> render(int accuracy = 4) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a segment of the curve by subdivision.
|
||||||
|
* @param start The starting point (between 0 and 1) on the curve.
|
||||||
|
* @param end The ending point on the curve.
|
||||||
|
* @param accuracy The 'fineness' of the curve.
|
||||||
|
* @returns A polygon chain that approximates the segment along the curve
|
||||||
|
**/
|
||||||
|
std::vector<Vector> renderSegment(double start, double end, size_t accuracy = 4) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Vector> controlPoints;
|
std::vector<Vector> controlPoints;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -94,6 +94,18 @@ int w_BezierCurve_insertControlPoint(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int w_BezierCurve_removeControlPoint(lua_State *L)
|
||||||
|
{
|
||||||
|
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||||
|
int idx = luaL_checkint(L, 2);
|
||||||
|
|
||||||
|
if (idx > 0) // 1-indexing
|
||||||
|
idx--;
|
||||||
|
|
||||||
|
luax_catchexcept(L, [&](){ curve->removeControlPoint(idx); });
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int w_BezierCurve_getControlPointCount(lua_State *L)
|
int w_BezierCurve_getControlPointCount(lua_State *L)
|
||||||
{
|
{
|
||||||
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||||
@@ -165,6 +177,28 @@ int w_BezierCurve_render(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int w_BezierCurve_renderSegment(lua_State *L)
|
||||||
|
{
|
||||||
|
BezierCurve *curve = luax_checkbeziercurve(L, 1);
|
||||||
|
double start = luaL_checknumber(L, 2);
|
||||||
|
double end = luaL_checknumber(L, 3);
|
||||||
|
int accuracy = luaL_optinteger(L, 4, 5);
|
||||||
|
|
||||||
|
std::vector<Vector> points;
|
||||||
|
luax_catchexcept(L, [&](){ points = curve->renderSegment(start, end, accuracy); });
|
||||||
|
|
||||||
|
lua_createtable(L, points.size()*2, 0);
|
||||||
|
for (size_t i = 0; i < points.size(); ++i)
|
||||||
|
{
|
||||||
|
lua_pushnumber(L, points[i].x);
|
||||||
|
lua_rawseti(L, -2, 2*i+1);
|
||||||
|
lua_pushnumber(L, points[i].y);
|
||||||
|
lua_rawseti(L, -2, 2*i+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg functions[] =
|
static const luaL_Reg functions[] =
|
||||||
{
|
{
|
||||||
{"getDegree", w_BezierCurve_getDegree},
|
{"getDegree", w_BezierCurve_getDegree},
|
||||||
@@ -172,12 +206,14 @@ static const luaL_Reg functions[] =
|
|||||||
{"getControlPoint", w_BezierCurve_getControlPoint},
|
{"getControlPoint", w_BezierCurve_getControlPoint},
|
||||||
{"setControlPoint", w_BezierCurve_setControlPoint},
|
{"setControlPoint", w_BezierCurve_setControlPoint},
|
||||||
{"insertControlPoint", w_BezierCurve_insertControlPoint},
|
{"insertControlPoint", w_BezierCurve_insertControlPoint},
|
||||||
|
{"removeControlPoint", w_BezierCurve_removeControlPoint},
|
||||||
{"getControlPointCount", w_BezierCurve_getControlPointCount},
|
{"getControlPointCount", w_BezierCurve_getControlPointCount},
|
||||||
{"translate", w_BezierCurve_translate},
|
{"translate", w_BezierCurve_translate},
|
||||||
{"rotate", w_BezierCurve_rotate},
|
{"rotate", w_BezierCurve_rotate},
|
||||||
{"scale", w_BezierCurve_scale},
|
{"scale", w_BezierCurve_scale},
|
||||||
{"evaluate", w_BezierCurve_evaluate},
|
{"evaluate", w_BezierCurve_evaluate},
|
||||||
{"render", w_BezierCurve_render},
|
{"render", w_BezierCurve_render},
|
||||||
|
{"renderSegment", w_BezierCurve_renderSegment},
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,12 +36,14 @@ int w_BezierCurve_getDerivative(lua_State *L);
|
|||||||
int w_BezierCurve_getControlPoint(lua_State *L);
|
int w_BezierCurve_getControlPoint(lua_State *L);
|
||||||
int w_BezierCurve_setControlPoint(lua_State *L);
|
int w_BezierCurve_setControlPoint(lua_State *L);
|
||||||
int w_BezierCurve_insertControlPoint(lua_State *L);
|
int w_BezierCurve_insertControlPoint(lua_State *L);
|
||||||
|
int w_BezierCurve_removeControlPoint(lua_State *L);
|
||||||
int w_BezierCurve_getControlPointCount(lua_State *L);
|
int w_BezierCurve_getControlPointCount(lua_State *L);
|
||||||
int w_BezierCurve_translate(lua_State *L);
|
int w_BezierCurve_translate(lua_State *L);
|
||||||
int w_BezierCurve_rotate(lua_State *L);
|
int w_BezierCurve_rotate(lua_State *L);
|
||||||
int w_BezierCurve_scale(lua_State *L);
|
int w_BezierCurve_scale(lua_State *L);
|
||||||
int w_BezierCurve_evaluate(lua_State *L);
|
int w_BezierCurve_evaluate(lua_State *L);
|
||||||
int w_BezierCurve_render(lua_State *L);
|
int w_BezierCurve_render(lua_State *L);
|
||||||
|
int w_BezierCurve_renderSegment(lua_State *L);
|
||||||
extern "C" int luaopen_beziercurve(lua_State *L);
|
extern "C" int luaopen_beziercurve(lua_State *L);
|
||||||
|
|
||||||
} // math
|
} // math
|
||||||
|
|||||||
Reference in New Issue
Block a user