Multiple objects in DirectX 9 - transformation and rendering

Started by
3 comments, last by belfegor 13 years, 7 months ago
Hi everybody!

I'm quite new to C++ and especially directX programming. I'm currently working on a very simple "Space Invaders" game, and by that I mean trying to get the very basics working.

Right now I have setup a basic window, loaded the .x model and have it transforming on the screen (just rotating). What I would like to do (for starters) is to have 2 objects of the same type (same model) on the screen, performing different transformations.

Now I think that in order to have multiple objects rendering on screen at 1 time, I will need to do this:

// Loop through all materials and draw each part of the model.
for(DWORD i = 0; i < numMaterials; i++)
{
D3D_Device->SetMaterial(&MaterialList);
D3D_Device->SetTexture(0, TextureList);

SpaceInvader_2->DrawSubset(i);
}

^^The above renders 1 mesh to screen (not 100% how it works, but it does :D).

I also have this code to transform the model every frame:

// This will hold the world matrix.
D3DXMATRIX WorldSpace;

//Buffer matrices
D3DXMATRIX M1;
D3DXMATRIX M2;

//Set the X-axis rotation value to the matrix M2
D3DXMatrixRotationX(&M2, angleX);

//Set the Y-axis rotation value to the matrix M1
D3DXMatrixRotationY(&M1, angleY);

//Multiply M1 and M2 matrices and store the resulting matrix in WorldSpace matrix
D3DXMatrixMultiply(&WorldSpace, &M1, &M2);

//Set the Z-axis rotation value to the matrix M1
D3DXMatrixRotationZ(&M1, angleZ);

//D3DXMatrixTranslation(WorldSpace, x, y, z);
D3DXMatrixMultiply(&WorldSpace, &WorldSpace, &M1);


// Set the matrix.
D3D_Device->SetTransform(D3DTS_WORLD, &WorldSpace);


//--------------------
The thing that I don't understand is how to have 2 meshes (from the same model .x file) in the scene at once, performing different transformations. I have been trying to find an answer in the directX documentation, but I wasn't able to.. Examples that do have more than 1 model on the screen, have WAAAAY to much other code, which makes it very confusing....

Any tips would be much appreciated!
Advertisement
D3DXMATRIX world1; // first transformation matrixD3DXMatrixIdentity(&world1);// sets world1 as current transfomation matrix// for all meshes drawn belowD3D_Device->SetTransform(D3DTS_WORLD, &world1);for(DWORD i = 0; i < numMaterials; i++){    D3D_Device->SetMaterial(&MaterialList); // sets material color    D3D_Device->SetTexture(0, TextureList); // sets texture    SpaceInvader_2->DrawSubset(i);}// now to draw same model but to different locationD3DXMATRIX world2; // second transf. mat.D3DXMatrixIdentity(&world2);D3DXMatrixTranslation(&world, -10.0f, 0.0f, 0.0f); // add little offset to the left// set world2, now all models drawn below will be transformed by this matrixD3D_Device->SetTransform(D3DTS_WORLD, &world2);// draw same modelfor(DWORD i = 0; i < numMaterials; i++){    D3D_Device->SetMaterial(&MaterialList); // sets material color    D3D_Device->SetTexture(0, TextureList); // sets texture    SpaceInvader_2->DrawSubset(i);}// repeat above for as many instances as you want
Thank you VERY much!! That's exactly what I needed!

One question though - what if (and this is just an example) you needed to create a thousand objects, in that way... is there a more efficient way of doing that? Just curious...
Then use geometry instancing:

http://msdn.microsoft.com/en-us/library/bb173349%28VS.85%29.aspx
I'v done this a bit different.
I choped it from my (unfinished framework) code for grass rendering:

in some init function
DWORD numInstances = 3000;if(0 != MeshX)	{		D3DVERTEXELEMENT9 VertexElementsGeom[] =		{			{0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,  0},			{0, 12, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,    0},			{0, 24, D3DDECLTYPE_FLOAT2,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  0},			{1, 0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  1},			{1, 16, D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  2},			{1, 32, D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  3},			{1, 48, D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  4},			D3DDECL_END()		};                 gvSizegeom = D3DXGetDeclVertexSize(VertexElementsGeom, 0);        gvSizeInst = D3DXGetDeclVertexSize(VertexElementsGeom, 1);		... ... 		dev->CreateVertexDeclaration(VertexElementsGeom, &gVDeclaration);		meshx->GetMesh()->GetVertexBuffer(&gVBufferGeom);		meshx->GetMesh()->GetIndexBuffer(&gIBuffer);		dev->CreateVertexBuffer(gvSizeInst * numInstances, D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &gVBufferInst, NULL);		Vector3D ppos, prot;	    ppos.SetAllZero();	    prot.SetAllZero();		for(int k = 0; k < numInstances; k++)		{			ppos = Vector3D(Math::Random(1000.0f) - 1000.0f, -90.0f, Math::Random(1000.0f) - 1000.0f);		    prot = Vector3D(0.0f, Math::Random(PI * 2.0f), 0.0f);			wrld[k].Identity();			wrld[k].SetRotation(prot);			wrld[k].SetTranslation(ppos);		}		Matrix4* pData = 0;		gVBufferInst->Lock(0, 0, (LPVOID*)&pData, 0);		memcpy(pData, wrld, gvSizeInst * numInstances);		gVBufferInst->Unlock();                ... ...}


then in render function
dev->SetVertexDeclaration(gVDeclaration);    dev->SetIndices(gIBuffer);	dev->SetStreamSourceFreq(0, (D3DSTREAMSOURCE_INDEXEDDATA | numInstances));	dev->SetStreamSource(0, gVBufferGeom, 0, gvSizegeom);    dev->SetStreamSourceFreq(1, (D3DSTREAMSOURCE_INSTANCEDATA | 1));	dev->SetStreamSource(1, gVBufferInst, 0, gvSizeInst);... ...gEffect->SetTechnique("tech");	gEffect->SetMatrix(...);	...	...	gEffect->SetTexture(...);	gEffect->SetFloat("timeNow", ...);	gEffect->Begin(0, 0);	gEffect->BeginPass(0);         dev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numVert, 0, numInd);	gEffect->EndPass();	gEffect->End();	dev->SetStreamSourceFreq(0, 1);	dev->SetStreamSourceFreq(1, 1);

This topic is closed to new replies.

Advertisement