Here is the non-optimized source of my twister used in "Goodbye Deliverance" intro.
Maybe it's helpfull for someone.
struct sRubber
{
float py[4];
};
class cRubber
{
public:
cRubber(float width, float height, float xOfs, float yOfs, float y_factor)
{
x_max = width;
y_max = height;
x_ofs = xOfs;
y_ofs = yOfs;
y_mul = y_factor;
half_y_mul = y_mul /2.0f;
//init basic rubber structure
mPos = 45.0f;
mLastStep = 0.0f;
mMove = 0.6f;
mIncSpeed = 0.0f;
mMoveSpeed = 0.000f;
mStep = 0;
mTurnLeft = false;
lstVertices = new sXYZ_D_0_Vertex[x_max*6];
memset(lstVertices,0,sizeof(sXYZ_D_0_Vertex)* x_max*6);
CreateVideoResources();
}
~cRubber()
{
delete[] lstVertices;
ReleaseVideoResources();
}
void Animate(float speed)
{
mIncSpeed = speed;
float maxMove = 0.6f;
//-- calculate movement
if ((mMove >= maxMove) | (mIncSpeed >= 0.3f))
{
mTurnLeft = true;
mIncSpeed = mTiming->TimedMove(0.25f)/10.0f;
}
if ((mMove <= -maxMove) | (mIncSpeed >= 0.3f))
{
mTurnLeft = false;
mIncSpeed = mTiming->TimedMove(0.25f)/10.0f;
}
if (mTurnLeft)
{
if (mMove > 0) mMoveSpeed -= mIncSpeed;
else mMoveSpeed += mIncSpeed;
}
else
{
if (mMove < 0) mMoveSpeed += mIncSpeed;
else mMoveSpeed -= mIncSpeed;
}
double tmpSpeed = mTiming->TimedMove(mMoveSpeed);
if (tmpSpeed > maxMove / 3.0f) tmpSpeed = maxMove / 3.0f;
mMove += tmpSpeed;
if (mMove > maxMove+0.2f) mMove = maxMove+0.2f;
if (mMove < -(maxMove+0.2f)) mMove = -(maxMove+0.2f);
//-- update VertexBuffer
sXYZ_D_0_Vertex *pMem = NULL;
pMem = lstVertices;
UINT pointOfs = 0;
mLines = 0;
if (m_hr == D3D_OK)
{
float tmpPos=mPos;
float lstY[4];
float txtXStep = 2.0f/x_max;
float txtXOfs = 0.0f;
float y_Color_Step = y_mul * 0.85f;
for (float x=(x_max/2.0f)*-1;x<x_max/2;x++)
{
lstY[0]=(y_mul*sinf((tmpPos)*oneD));
lstY[1]=(y_mul*sinf((tmpPos+90)*oneD));
lstY[2]=(y_mul*sinf((tmpPos+180)*oneD));
lstY[3]=(y_mul*sinf((tmpPos+270)*oneD));
int toY;
for (int i=0; i<4; i++)
{
if (i==3) toY=0;
else toY=i+1;
if (lstY[toY]>lstY[i])
{
float linLength = (lstY[toY]-lstY[i]);
float colorMul = linLength/y_Color_Step;
pMem[pointOfs].px = x;
pMem[pointOfs].py = lstY[i];
pMem[pointOfs].pz = 0.0f;
pMem[pointOfs].color = D3DXCOLOR( colorMul, colorMul,colorMul, 1.0f );
pMem[pointOfs].tu = txtXOfs;
pMem[pointOfs].tv = 0.0f;
pMem[pointOfs+1].px = x;
pMem[pointOfs+1].py = lstY[toY];
pMem[pointOfs+1].pz = 0.0f;
pMem[pointOfs+1].color = D3DXCOLOR( colorMul, colorMul, colorMul, 1.0f );
pMem[pointOfs+1].tu = txtXOfs;
pMem[pointOfs+1].tv = 1.0f;
pointOfs += 2;
mLines++;
}
}
txtXOfs += txtXStep;
tmpPos+=mMove;
}
}
sXYZ_D_0_Vertex *pVB = NULL;
m_hr = pVb->Lock(0,0,(VOID**)&pVB,D3DLOCK_DISCARD);
memcpy(pVB,pMem,sizeof(sXYZ_D_0_Vertex)*mLines*2);
pVb->Unlock();
m_hr = pRenderTarget->GetSurfaceLevel(0, &pSurface);
m_hr = d3d_dev->SetRenderTarget(0,pSurface);
m_hr = d3d_dev->SetDepthStencilSurface(TargetStencil);
d3d_dev->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,RGB(0,0,0),1,0);
D3DVIEWPORT9 tmpVP = {0,0,512,256,0.0f,1.0f};
m_hr = d3d_dev->SetViewport(&tmpVP);
d3d_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
d3d_dev->SetTexture(0,pTexture);
d3d_dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
d3d_dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE ,TRUE);
d3d_dev->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
d3d_dev->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
d3d_dev->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
d3d_dev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
d3d_dev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
m_hr = d3d_dev->SetStreamSource(0, pVb, 0, sizeof(sXYZ_D_0_Vertex));
m_hr = d3d_dev->SetVertexShader(NULL);
m_hr = d3d_dev->SetFVF(D3DFVF_XYZ_D_0);
m_hr = d3d_dev->DrawPrimitive(D3DPT_LINELIST,0,mLines);
m_hr = d3d_dev->SetRenderTarget(0,mpBack);
m_hr = d3d_dev->SetDepthStencilSurface(mpStencil);
}
void Draw()
{
d3d_dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
d3d_dev->SetTexture(0,pRenderTarget);
d3d_dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
d3d_dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE ,TRUE);
d3d_dev->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
d3d_dev->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
d3d_dev->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
d3d_dev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
d3d_dev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
m_hr = d3d_dev->SetStreamSource(0, pVBRec, 0, sizeof(sLogoVertex));
m_hr = d3d_dev->SetVertexShader(NULL);
m_hr = d3d_dev->SetFVF(D3DFVF_XYZ_0);
m_hr = d3d_dev->DrawPrimitive(D3DPT_TRIANGLELIST,0,2);
d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE ,FALSE);
d3d_dev->SetTexture(0,NULL);
}
void CreateVideoResources()
{
//-- Create Rendertarget
m_hr = d3d_dev->CreateTexture(512,256,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pRenderTarget,NULL);
m_hr = d3d_dev->CreateDepthStencilSurface(512,256,d3dpp.AutoDepthStencilFormat,d3dpp.MultiSampleType,
d3dpp.MultiSampleQuality,false,&TargetStencil,NULL);
// VertexBuffer aufbauen
d3d_dev->CreateVertexBuffer(6 * sizeof(sLogoVertex),
D3DUSAGE_DYNAMIC, D3DFVF_XYZ_0,
D3DPOOL_DEFAULT, &pVBRec, NULL);
sLogoVertex *pMem=NULL;
pVBRec->Lock(0,0,(void**)&pMem,D3DLOCK_DISCARD);
float tmpx=8.0f,tmpy=2.0f;
//Tri0
pMem[0].px = (tmpx / 2) * (-1);
pMem[0].py = (tmpy / 2) * (-1);
pMem[0].pz = 0.0f;
pMem[0].tu = 0.0f;
pMem[0].tv = 0.5f;
pMem[1].px = (tmpx / 2) * (-1);
pMem[1].py = (tmpy / 2);
pMem[1].pz = 0.0f;
pMem[1].tu = 0.0f;
pMem[1].tv = 0.0f;
pMem[2].px = (tmpx / 2);
pMem[2].py = (tmpy / 2);
pMem[2].pz = 0.0f;
pMem[2].tu = 1.0f;
pMem[2].tv = 0.0f;
//Tri1
pMem[3].px = (tmpx / 2);
pMem[3].py = (tmpy / 2) * (-1);
pMem[3].pz = 0.0f;
pMem[3].tu = 1.0f;
pMem[3].tv = 0.5f;
pMem[4].px = (tmpx / 2) * (-1);
pMem[4].py = (tmpy / 2) * (-1);
pMem[4].pz = 0.0f;
pMem[4].tu = 0.0f;
pMem[4].tv = 0.5f;
pMem[5].px = (tmpx / 2);
pMem[5].py = (tmpy / 2);
pMem[5].pz = 0.0f;
pMem[5].tu = 1.0f;
pMem[5].tv = 0.0f;
pVBRec->Unlock();
m_hr = D3DXCreateTextureFromFileInMemoryEx(d3d_dev,(void*)&textur_twister_neu,textur_twister_neuBytes,256,256,1,D3DUSAGE_DYNAMIC,D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
D3DX_FILTER_NONE, D3DX_FILTER_NONE, RGB(0,0,0), NULL, NULL, &pTexture);
D3DSURFACE_DESC SurfDesc;
D3DLOCKED_RECT LockRect;
RECT Rect;
d3d_dev->CreateVertexBuffer(x_max*6*sizeof(sXYZ_D_0_Vertex),D3DUSAGE_DYNAMIC,D3DFVF_XYZ_D_0,D3DPOOL_DEFAULT,&pVb,NULL);
}
void ReleaseVideoResources()
{
pTexture->Release();
pVb->Release();
pRenderTarget->Release();
pSurface->Release();
TargetStencil->Release();
}
float mMove, mIncSpeed;
private:
float x_ofs, y_ofs, x_max, y_max, y_mul, half_y_mul;
IDirect3DTexture9 *pTexture;
IDirect3DTexture9 *pRenderTarget;
IDirect3DSurface9 *pSurface;
IDirect3DVertexBuffer9 *pVb;
IDirect3DVertexBuffer9 *pVBRec;
IDirect3DSurface9 *TargetStencil;
double mPos, mMoveSpeed;
bool mTurnLeft;
UINT mStep, mLastStep, mLines;
sXYZ_D_0_Vertex *lstVertices;
};