Jump to content
  • Advertisement
Sign in to follow this  
mengha

Multiple Objects

This topic is 4797 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I learning through the "Intoruction to 3D game programming with DirectX 9.0" book and have got as far as being learning how to draw a spinning cube. After a bit of messing around I figured out how to use D3DXCreateTeapot() to create a teapot and draw that. I can render both but they both spin together and are in the same position. My question is how do I render objects in different places and how do I make them spin seperate to each other? CAn anyone give me a push in the right direction? this is the code im using to draw and rotate the cube:
float currtime = (float)timeGetTime();
			float timedelta = (currtime - lasttime) * 0.001f;

			D3DXMATRIX Rx, Ry;

			static float y = 0.0f;
			static float x = 0.0f;

			D3DXMatrixRotationX(&Rx, x);

			x += timedelta;

			if(x >= 6.28f)
			{
				x = 0.0f;
			}

			D3DXMatrixRotationY(&Ry, y);

			y += timedelta;

			if(y >= 6.28f)
			{
				y = 0.0f;
			}

			D3DXMATRIX p = Rx * Ry;

			d3ddevice->SetTransform(D3DTS_WORLD, &p);

			d3ddevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);

			d3ddevice->BeginScene();
			d3ddevice->SetStreamSource(0, VB, 0, sizeof(MyVertex));
			d3ddevice->SetIndices(IB);
			d3ddevice->SetFVF(MyVertex::FVF);
			d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
			d3ddevice->EndScene();

			d3ddevice->Present(0,0,0,0);

			lasttime = currtime;

To render the teapot i just use mesh->DrawSubset(0); Thanks for any help

Share this post


Link to post
Share on other sites
Advertisement
When using the fixed function vertex pipeline (i.e. not using vertex shaders), all your untransformed (i.e. non D3DFVF_XYZRHW) vertices are affected by 3 matrices: The world, view and projection matrices. The world matrix controls things such as the object size, position and orientation. So in your case, simply do a separate:
d3ddevice->SetTransform(D3DTS_WORLD, &matrix);
..for each object you have.

Share this post


Link to post
Share on other sites
Are vertices transformed when sent to the vertex buffer, or do they get transformed when they are drawn? I guess it wouldnt really make sense to be transformed when they are drawn, but its good to be sure.

Share this post


Link to post
Share on other sites
Well, they are in fact transformed just when they need to be drawn. This makes sense, since polygons which fail the frustum check (usually a notable percentage of polygons drawn) do not need to go through the vertex processing pipeline at all.

Thinking of vertex shaders, you could also draw a single vertex buffer with different shaders, if the shader would be applied to the vertex buffer, instead of on-the-fly when drawing takes place, the vertex buffer would be modified each time you call SetStreamSource() or wherever you would intend on putting the transformation stage then - not a good idea if you compare the speed of static and dynamic vertex buffers ;)

-Markus-

Share this post


Link to post
Share on other sites
True.

But then how are you supposed to set different transforms for different "world" objects? For instance, if you have 14 rocks, all have different world locations and orientations. How are these applied?

Share this post


Link to post
Share on other sites
Quote:
Original post by Bonehed316
But then how are you supposed to set different transforms for different "world" objects? For instance, if you have 14 rocks, all have different world locations and orientations. How are these applied?

Four options:

1. Multiple draw calls
This is the traditional method; store one rock and 14 matrices. Pair up D3D calls like:


Device->SetStreamSource( ... );
Device->SetIndices( ... );
//etc...
for( int i = 0; i < 14; i++ )
{
Device->SetTransform( D3DTS_WORLD, &rockMatrix );
Device->DrawIndexedPrimitive( ... );
}


2. Extra data
Store 14 copies of similar geometry in your vertex buffer, pre-transformed accordingly. Submit them all as one big draw call.

Not recommended though [smile] - works okay for small sets of static objects, but falls apart when you have large numbers of objects and/or need to update their transformation.

3. Vertex shaders and constants
Some system where you combine #1 and #2 (above) but get the GPU/shader to work out what should be going on. For example, pass various constants/params to the shader so that it can calculate the rotations/translations accordingly.

4. Instancing
A fairly advanced feature available in the latest-and-greatest hardware. Does pretty much exactly what you want in possibly the most efficient possible way. However, support for it isn't really there yet - so i'd class it more of an optimization opportunity than a base-feature.

hth
Jack

Share this post


Link to post
Share on other sites
Quote:
Original post by Bonehed316
So you pretty much have to call DIP for every object, and for every texture/render state, I guess.

Yep[attention]

A lot of work done by engine programmers is on algorithms/arrangements/scheduling to reduce the number of state changes and draw calls that are required to render a given scene. Huuuge performance gains are possible [grin]

hth
Jack

Share this post


Link to post
Share on other sites
Ok I have managed to draw them apart using:


d3ddevice->BeginScene();

d3ddevice->SetStreamSource(0, VB, 0, sizeof(MyVertex));
d3ddevice->SetIndices(IB);
d3ddevice->SetFVF(MyVertex::FVF);

//Cube
D3DXMatrixTranslation(&p, -1.25f, 0.0f, 0.0f);
d3ddevice->SetTransform(D3DTS_WORLD, &p);
d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);

//Teapot
D3DXMatrixTranslation(&p, 1.25f, 0.0f, 0.0f);
d3ddevice->SetTransform(D3DTS_WORLD, &p);
mesh->DrawSubset(0);

d3ddevice->EndScene();



But Im still confused about rotating each of them seperatly using the code in my first post. :S

Share this post


Link to post
Share on other sites
Well you have two choices. The two rotations can be separate or related. If you just let them spin at the same rate then it's easy:


float currtime = (float)timeGetTime();
float timedelta = (currtime - lasttime) * 0.001f;
D3DXMATRIX Rx, Ry, Translation;

static float y = 0.0f;
static float x = 0.0f;

D3DXMatrixRotationX(&Rx, x);

x += timedelta;

if(x >= 2.0f * D3DX_PI)
x = 0.0f;

D3DXMatrixRotationY(&Ry, y);

y += timedelta;

if(y >= 2 * D3DX_PI)
y = 0.0f;

D3DXMatrixTranslation(&Translation, 1.5f, 0.0f, 0.0f);

D3DXMATRIX p = Rx * Ry * Translation;

d3ddevice->SetTransform(D3DTS_WORLD, &p);

d3ddevice->DrawPrimitive(...);

D3DXMatrixTranslation(&Translation, -1.5f, 0.0f, 0.0f);

p = Rx * Ry * Translation

d3ddevice->SetTransform(D3DTS_WORLD, &p);

mesh->DrawSubset(0);


If you want them to be indepdant of each other I'm afraid it gets a little more complicated. Here's one possiblity:


struct WorldMatrix
{
D3DXVECTOR3 position;
float RotationX, RotationY, RotationZ;
D3DXMATRIX GetMatrix()
{
D3DXMATRIX matrix, rx, ry, rz, translation;

while(RotationX >= 2.0f * D3DX_PI) RotationX -= 2.0f * D3DX_PI;
while(RotationY >= 2.0f * D3DX_PI) RotationY -= 2.0f * D3DX_PI;
while(RotationZ >= 2.0f * D3DX_PI) RotationZ -= 2.0f * D3DX_PI;

D3DXMatrixRotationX(&rx, RotationX);
D3DXMatrixRotationX(&ry, RotationY);
D3DXMatrixRotationX(&rz, RotationZ);
D3DXMatrixTranslation(&translation, position.x, position.y, position.z);
matrix = ry * rx * rz * translation;
return matrix;
}
};


float currtime = (float)timeGetTime();
float timedelta = (currtime - lasttime) * 0.001f;

static WorldMatrix Teapot;
static WorldMatrix Box;

Teapot.RotationX += timedelta;
Box.RotationX += timedelta;

Teapot.RotationY += timedelta;
Box.RotationY += timedelta;

d3ddevice->SetTransform(D3DTS_WORLD, &Box.GetMatrix());

d3ddevice->DrawPrimitive(...);

d3ddevice->SetTransform(D3DTS_WORLD, &Teapot.GetMatrix());

mesh->DrawSubset(0);






If you don't understand what that second example is doing, post back here and I (or one of many other kind folks) will try to explain.

Hope that helps!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!