Use simple linear interpolation to implement interesting curves and animations

Source: Internet
Author: User

<Use simple linear interpolation to implement interesting curves and animations>
Tags: opengl, 3d, c, linux

1. What should I implement?

For better illustration, let's first take a look at what we want to achieve. Since it is the effect of a graph, naturally it is best to see the graph.
Clarify the problem.

1) curve to be drawn:

./BMP _line/sshot_1_bmp



2) animation to be implemented:

./BMP _line/animated.gif



2. Geometric Analysis

./Lerp.note.bmp

We can see that what we finally want to draw is a red curve, and the red curve is obviously composed
Some line segments are connected. To determine a line segment, it is almost impossible to find its two endpoints.
The question is already clear: how to find the endpoint? We can see that these endpoints are of various diagonal lines and crosslines.
Point of intersection. Therefore, this problem is transformed into: finding the point of intersection of two straight lines.

3. functions related to two straight lines

3.1 calculate the straight line after the known two points

The linear equation is y = k * x + B.

Two points (x1, y1) and (x2, y2) are known, and k and B are obtained:

Y1 = k * x1 + B \/k = (y2-y1)/(x2-x1)
| ==>|
Y2 = k * x2 + B/\ B = y1-k * x1

3.2 calculate the intersection of two straight lines

The linear equation is Y = K * x + B.

Two straight lines are known,
Y = K1 * x + B1
Y = k2 * x + b2
Calculate the intersection of them (x, y ):

Y = K1 * x + B1 \/x = (B2-B1 )/
(K1-K2)
| ==>|
Y = k2 * x + b2/\ y = K1 * x + B1

3.3 code implementation

/* * y = k*x + b * * y1 = k*x1 + b \       / k =(y2 - y1) / (x2 - x1) *                | ==> | * y2 = k*x2 + b /       \ b = y1 - k*x1 * * */int  N3D_lineConstruct(float x1, float y1, float x2, float y2,        float *k, float *b){    assert( !(x1 == x2 && y1 == y2) );    if ( x1 == x2 )    {        return 0;    }    *k = (y2 - y1) / (x2 - x1);    *b = y1 - (*k) * x1;    return 1;}/* * y = k*x + b * * y = k1*x + b1 \      / x =(b2 -b1) / (k1 - k2) *                | ==> | * y = k2*x + b2 /      \ y = k1*x + b1 * * */int  N3D_lineInsertPos(float k1, float b1, float k2, float b2,        float *x, float *y){    if ( k1 == k2 )    {        return 0;    }    *x = (b2 - b1) / (k1 - k2);    *y = k1 * (*x) + b1;    return 1;}


4. Start to implement what we want to implement

4.1 curves (static)

Typedef struct n3d_vertex {float FX; float FY; float FZ; float FS; float ft;} n3d_vertex; typedef struct n3d_godpos {float mftarx; // control axis (black solid line in the figure) the X coordinate float mftary of the bottom end point; // The Y coordinate float mftarw of the bottom end point of the control axis (black solid line in the figure); // The float mftarh of the control axis width; // control axis height int mnframexpend; // Number of frames in the second half of the animation int mndivy; // Number of frames in the first half of the animation n3d_vertex * mvvex; // float * mvhelpx of vertex data; // used for the second half of the secondary animation} n3d_godpos; n3d_godpos g_godpos = {0.0,-1.0, 0.0, 1.0, 10, 20, null, null ,};

First define and initialize a curve we want to implement: g_godpos!

void N3D_godUpdatePos(N3D_GodPos *god){    assert(god != NULL && god->mvVex != NULL && god->mnDivY > 0);    int     i;    float   fCcen = god->mfTarH / (float)god->mnDivY;    float   fEcen = 2.0 / (float)god->mnDivY;    float   fTexCen = 1.0 / (float)god->mnDivY;    for ( i = 0; i <= god->mnDivY; i++ )    {        N3D_godSTcalCurvePos(god, i, fCcen, fEcen, fTexCen);    }}

Figure:./BMP _point/sshot_1_bmp

First, we implement a function used to calculate the vertex data of the final curve: n3d_godupdatepos, which is calculated by row,
Total (God-> mndivy + 1) rows. The final call is n3d_godstcalcurvepos,

static void N3D_godSTcalCurvePos(N3D_GodPos *god, int i, float fCcen,        float fEcen, float fTexCen){    assert(god != NULL && god->mvVex != NULL && god->mnDivY > 0);    assert(i >= 0 && i <= god->mnDivY);    // Normal Rect: [(-1.0, 1.0), (1.0, -1.0)], size is 2.0    const float     rectLTX = -1.0;    const float     rectLTY =  1.0;    const float     rectBRX =  1.0;    const float     rectBRY = -1.0;    float Cx1 = god->mfTarX;    float Cy1 = god->mfTarY + fCcen * i;    float CxL = rectLTX;    float CyL = rectLTY;    float CxR = rectBRX;    float CyR = rectLTY;    float Ex1 = -1.0;    float Ey1 = rectBRY + fEcen * i;    float Ex2 =  0.0;    float Ey2 = Ey1;    float Ck, Cb, Ek, Eb, insPosXL, insPosYL, insPosXR, insPosYR;    N3D_Vertex  *pV = god->mvVex;    if ( Cx1 == CxL ) CxL += 0.00001;    N3D_lineConstruct(Cx1, Cy1, CxL, CyL, &Ck, &Cb);    N3D_lineConstruct(Ex1, Ey1, Ex2, Ey2, &Ek, &Eb);    if ( Ck == Ek ) Ek += 0.00001;    N3D_lineInsertPos(Ck, Cb, Ek, Eb, &insPosXL, &insPosYL);    Cx1 += god->mfTarW;    if ( Cx1 == CxR ) CxR += 0.00001;    N3D_lineConstruct(Cx1, Cy1, CxR, CyR, &Ck, &Cb);    if ( Ck == Ek ) Ek += 0.00001;    N3D_lineInsertPos(Ck, Cb, Ek, Eb, &insPosXR, &insPosYR);    pV[2*i].fX = insPosXL;    pV[2*i].fY = insPosYL;    pV[2*i].fZ = 0.0;    pV[2*i].fS = 0.0;    pV[2*i].fT = fTexCen * i;    pV[2*i+1].fX = insPosXR;    pV[2*i+1].fY = insPosYR;    pV[2*i+1].fZ = 0.0;    pV[2*i+1].fS = 1.0;    pV[2*i+1].fT = fTexCen * i;}

Calculate the intersection of two straight lines and save it to God-> mvvex.

The next step is rendering. With vertex data, rendering is very clear:

void N3D_godDraw(N3D_GodPos *god){    assert(god != NULL && god->mvVex != NULL && god->mvHelpX != NULL            && god->mnDivY > 0);    int i;    N3D_Vertex *pV = god->mvVex;    glBegin(GL_TRIANGLE_STRIP); {        for ( i = 0; i <= god->mnDivY; i++ )        {            glTexCoord2f(pV[2*i].fS, pV[2*i].fT);            glVertex3f(pV[2*i].fX, pV[2*i].fY, pV[2*i].fZ);            glTexCoord2f(pV[2*i+1].fS, pV[2*i+1].fT);            glVertex3f(pV[2*i+1].fX, pV[2*i+1].fY, pV[2*i+1].fZ);        }    } glEnd();}

4.2 Animation

With our previous analysis and implementation, animation can be easily implemented. Let's take a look at the principle:

The entire process is divided into (God-> mndivy + 1) frame rendering, the first frame draws the first line, the second frame draws the first two
Line ,...

static void N3D_godSTdrawAminDemo(N3D_GodPos *god){    assert(god != NULL && god->mvVex != NULL && god->mvHelpX != NULL            && god->mnDivY > 0 && god->mnFramExpend > 0);    int j;    N3D_godinit(&g_godPos, 0);    for ( j = 0; j <= god->mnDivY + god->mnFramExpend; j++ )    {        N3D_godClear();        glPushMatrix(); {            glEnable(GL_TEXTURE_2D);            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);            glPointSize(3);            glColor4f(1.0, 1.0, 0.0, 1.0);            glScalef(0.5, 0.5, 0.5);            N3D_godDrawAminByLine(god, j);        } glPopMatrix();        N3D_godFlush();        usleep(20 * 1000);    }}void N3D_godDrawAminByLine(N3D_GodPos *god, int curLine){    assert(god != NULL && god->mvVex != NULL && god->mvHelpX != NULL            && god->mnDivY > 0 && god->mnFramExpend > 0);    assert(curLine >= 0 && curLine <= god->mnDivY + god->mnFramExpend);    if ( curLine <= god->mnDivY )    {        N3D_godUpdatePosByLine(god, curLine);    }    else    {        N3D_godSTupdateFramExpendPos(god, curLine);    }    N3D_godDrawByLine(god, curLine);}

5. Other Curves

The advantage of linear interpolation is that it can be drawn without the first known curve equation, and its computing workload is obviously not that
It's big.

N3d_godpos g_godpos = {0.0,-1.0, 0.3, 1.0, 10, 20, null}; // Tree Type

Figure:./animated-tree.gif



N3d_godpos g_godpos = {0.0,-0.4, 0.3, 1.0, 10, 20, null}; // crossover type

Figure:./animated-cross.gif



N3d_godpos g_godpos = {0.0,-1.0, 0.3,-3.0, 10, 20, null}; // Bowl Type

Figure:./animated-bowl.gif



N3D_GodPos g_godPos = {0.0,-0.1, 0.1,-3.0, 10, 20, NULL}; // wine cup type

Figure:./animated-glass.gif


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.