VertexTweening

Started by
13 comments, last by pawelp 22 years ago
How can I do VertexTweening? I have tow 3DModels (or better two versions of the same model) and want to simulate a moving? How can I tell DirectX to Tween betwen them? (I use Delphi but I will be also heppy about some C Code, so far it will keep simple...)
Advertisement
I have some BCB code I can post when I get home if that's OK......

Neil

PS it uses Vertex Shaders if you're comfortable with that....

WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!

[edited by - thedo on March 21, 2002 8:46:19 AM]
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
If you just could add some comment s that woud be great!

My knowledge about Vertex Shaders isn''t the best, but I hope it will be enought
Heres the vertex shader (The hardest part)

//Vertex shader for tweening between 2 models
;-----------------------------------------------------------------------------
; Note that my MD2 models have no normals so need no lighting calculations
; v0 Vertex1
; v1 Vertex2
; v3 color1
; v4 color2
; v6 texturecoord1
; v7 texturecoord2
;
; r0 temp vertex 1
; r1 temp vertex 2
;
; c0 tween value
; c1-c4 world matrix
; c6-c9 projection-view matrix
;
; oPos Output vertex
; oTn texture out
;
;-----------------------------------------------------------------------------
vs.1.1

//take the first vertex from the second vertex
mov r0,v0
add r1,v1,-r0

//Multliply the result by the tween factor
mul r2,c0,r1
//mov r0,v0
//Add the result to the first vertex
add r0,v0,r2

//multiply result by matrix to get final output
dp4 r1.x, r0, c1
dp4 r1.y, r0, c2
dp4 r1.z, r0, c3
dp4 r1.w, r0, c4


dp4 oPos.x, r1, c6
dp4 oPos.y, r1, c7
dp4 oPos.z, r1, c8
dp4 oPos.w, r1, c9

//copy texture coords and color
mov oT0,v6
mov oD1,v3


This is the Shader Declaration

DWORD decl[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh
D3DVSD_REG( 3, D3DVSDT_D3DCOLOR ),
D3DVSD_REG( 6, D3DVSDT_FLOAT2 ),
D3DVSD_STREAM( 1 ),
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // Position of second mesh
D3DVSD_REG( 4, D3DVSDT_D3DCOLOR ),
D3DVSD_REG( 7, D3DVSDT_FLOAT2 ),
D3DVSD_END()
};

Heres the rendering code

D3DXMATRIX mat;
D3DXMatrixMultiply( & mat, & view, & proj );
D3DXMatrixTranspose( & mat, & mat );
float v[4]={part,part,part,1};
Device->SetVertexShaderConstant( 0, &v, 1 );
Device->SetVertexShaderConstant( 1, &matWorldTranspose, 4 );
Device->SetVertexShaderConstant( 6, &mat,4);
Device->SetVertexShader (handle);
Device->SetStreamSource(0,Frames[(int)pFrame],sizeof(MODELVERTEX));
Device->SetStreamSource(1,Frames[(int)pFrame+1],sizeof(MODELVERTEX));
Device->DrawPrimitive(D3DPT_TRIANGLELIST,0,(m_triangles));

And finally the FVF I''m using is

// The vertex we use for D3D
struct MODELVERTEX
{
D3DXVECTOR3 m_vecPos; //Position
D3DCOLOR m_dwDiffuse; //Color
D3DXVECTOR2 m_vecTex; //texturecoordinates
};

//This is the definition for the vertex declared above (FVF=flexible vertex format)
#define D3DFVF_MODELVERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 )

Any Questions Post them or e-mail me and I''ll see what I can do.

Neil

PS I cant vouch that this is the BEST WAY of doing it but it works pretty well.

Neil

WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
ehm.. yes .. there are some questions.

1.
At first the code above the Shader declaration ("DWORD decl[] =
") looks a bit like assembler (mo,add..) is this something that I have to do or is it just a description of whot is done by irectX?

2.
The Shader Declaration:
I''m not so familiar wih C, so I have to interpret the decl first, correct me if I''m wrong.
decl is the name of a array of type dword, right?
And where is it used?

3.
Render Code:
//Why do you multiply the View and the Projection Matrix?
D3DXMatrixMultiply( & mat, & view, & proj );

//Why Transpose?
D3DXMatrixTranspose( & mat, & mat );

//what is part?
float v[4]={part,part,part,1};

//Whhat dose it do?
Device->SetVertexShaderConstant( 0, &v, 1 );
Device->SetVertexShaderConstant( 1, &matWorldTranspose, 4 );
Device->SetVertexShaderConstant( 6, &mat,4);

//handle will be the FVF format definition, right?
Device->SetVertexShader (handle);

// The "Frames[(int)pFrame]" will be a array with your VertexBuffer?
//So we set here the two models to tween between, but from where DirectX koows how far it shat tween(maybe the SetVertexShaderConstant)?
Device->SetStreamSource(0,Frames[(int)pFrame],sizeof(MODELVERTEX));
Device->SetStreamSource(1,Frames[(int)pFrame+1],sizeof(MODELVERTEX));

Device->DrawPrimitive(D3DPT_TRIANGLELIST,0,(m_triangles));



I hope the questions don''t sound to stupid
Thanx for the code.
1: It is D3D Vertex shader assembler. Look in the DX SDK as to what each instruction does.

2: Yes partyly my fault I missed a bit of code. It is an array.
When you assemble your VS code (in an external file)like this:

D3DXAssembleShaderFromFile( "c:\\Tween.vsh", 0, NULL,&vsFunction, NULL );
Device->CreateVertexShader( decl, (DWORD*)vsFunction->GetBufferPointer(), &handle, D3DUSAGE_SOFTWAREPROCESSING );
You create a Handle to the shader (as used in Question3)

3: In the SDK Docs it explains all. VS only used transposed combined view and Projection matrices. Don't know WHY. Just do it.

How does it know how far to tween - well that is the part variable. Passed to the VS in c0.

Have a look at the Docs and see what you can get. I figured it out from that and using this place. Post back when you have had a look at the docs. VS coe is nt trivial BUT it's not too hard either. The SDK teaches it better than I can.

I will post a Complete SIMPLE VS later for you to look at.

Neil

WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!

[edited by - thedo on March 21, 2002 12:43:20 PM]
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
Okey, I read now some bit about the VertexShader (I spend the half last night for it...), and I think that I start to understand... can I have the promised sample ?
Oops yeah almost forgot. I''m at Uni right now so I will post it later. PROMISE.....

Neil

WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
OK First thing is first. Create a text file and name it basic.vsh

copy this into it.

vs.1.1


//multiply result by matrix to get final output
dp4 r1.x, r0, v0.x
dp4 r1.y, r0, v0.y
dp4 r1.z, r0, v0.z
dp4 r1.w, r0, v0.w

dp4 oPos.x, r1, c6
dp4 oPos.y, r1, c7
dp4 oPos.z, r1, c8
dp4 oPos.w, r1, c9

This is just the most basic VS I can think of - it acts just like the standard T+L (but withut any lighting).

In your code

DWORD handle;
LPD3DXBUFFER vsFunction;

DWORD decl[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3), //Pass only vertex to shader
D3DVSD_END()
};

D3DXAssembleShaderFromFile( "basic.vsh", 0, NULL,&vsFunction, NULL );
Device->CreateVertexShader( decl, (DWORD*)vsFunction->GetBufferPointer(), &handle, D3DUSAGE_SOFTWAREPROCESSIND3DXMATRIX mat;
D3DXMatrixMultiply( & mat, & view, & proj );
D3DXMatrixTranspose( & mat, & mat );
Device->SetVertexShaderConstant( 1, &matWorldTranspose, 4 );
Device->SetVertexShaderConstant( 6, &mat,4);
Device->SetVertexShader (handle);
Device->SetStreamSource(0,Frames[(int)pFrame],sizeof(MODELVERTEX));
Device->DrawPrimitive(D3DPT_TRIANGLELIST,0,(m_triangles));

This is the FVF

struct MODELVERTEX
{
D3DXVECTOR3 m_vecPos; //Position
};

//This is the definition for the vertex declared above (FVF=flexible vertex format)
#define D3DFVF_MODELVERTEX ( D3DFVF_XYZ )

Hope this helps

Neil







WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
WHATCHA GONNA DO WHEN THE LARGEST ARMS IN THE WORLD RUN WILD ON YOU?!?!
Is it necceserry to call D3DXAssembleShaderFromFile each frame? Or is it enought to call it once, create a handle to it and than use it in the render procedure?

Ot the weekend I get an ezample where the whole tweening translation is done manualty like:

TriangleToRender.x := Triangle[FirstFrame] + TimeKey * (Triangle[NextFrame].x-Triangle[FirstFrame].x);

This method have the great disadvantege that you have to go throught all the Triangles in a model and throught x,y,z, normals and textureCoordinates off all them...
It isn''t right slow but I''m asking myself if the VertexShaders are faster?

This topic is closed to new replies.

Advertisement