Direct3d help

(moved from Windows programming, since this forum seems to get a lot more use)

Okay, so I brushed off a d3d9 app and I'm trying to spruce it up a bit. But, I haven't touched the stuff since college, and even then only understood a fraction of what was going on. I'm working on a lego man for now. Pics can be found at:
http://i.imgur.com/N2E7Y.jpg
http://i.imgur.com/yUUfw.jpg

A lego guy for reference: http://irn-bru.deviantart.com/art/LEGO-Man-Terry-94679702

So I want some advice on how to improve and learn, especially with regard to shading. All the objects making up the lego man are custom 'box' and 'cylinder' objects, with the exception of the top of his head, which is a d3dx sphere.

1) Notice in the first pic, his left leg is my attempt to improve normals a bit. But you can't see the 'thigh' portion of that leg. How should the normals be located for this to be visible in a natural way? Right now the normal on the outside front of his thigh intersection with shin is set to (1, -1, 1) - can this be improved? (I haven't done the foot yet, as there actually isn't a vertex in the middle of the foot...I will add one for the normal)

2) Very obviously, the top of the head is much shinier than the rest of him. What does D3DXCreateSphere do differently? (code below)

3) What is the best way to handle the face? Will adding a texture screw with the shading?

4) Any general suggestions on how to improve lighting, or other things I may not have thought of?

Lighting setup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Set up a material. The material here just has the diffuse and ambient
    // colors set to yellow. Note that only one material can be used at a time.
    D3DMATERIAL9 mtrl;
    ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
    mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
    mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
    mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;
    mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
    myD3D->g_pd3dDevice->SetMaterial( &mtrl );

    // Set up a white, directional light, with an oscillating direction.
    // Note that many lights may be active at a time (but each one slows down
    // the rendering of our scene). However, here we are just using one. Also,
    // we need to set the D3DRS_LIGHTING renderstate to enable lighting
    D3DXVECTOR3 vecDir;
    D3DLIGHT9 light;
    ZeroMemory( &light, sizeof(D3DLIGHT9) );
    light.Type       = D3DLIGHT_DIRECTIONAL;
    light.Diffuse.r  = 1.0f;
    light.Diffuse.g  = 1.0f;
    light.Diffuse.b  = 1.0f;
    vecDir = D3DXVECTOR3(0.5f,//cosf(timeGetTime()/350.0f),
                         -4.0f,
                         -1.0f);//sinf(timeGetTime()/350.0f) );
    D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir );
    light.Range       = 2000.0f;
    myD3D->g_pd3dDevice->SetLight( 0, &light );
    myD3D->g_pd3dDevice->LightEnable( 0, TRUE );
    myD3D->g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

    // Finally, turn on some ambient light.
    myD3D->g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00262626 );


Box code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
if(m_pVB == NULL || m_pIB == NULL)
	{
		CUSTOMVERTEX * gVertPool  = new CUSTOMVERTEX[8];

		// Back top right
		gVertPool[0].x = m_TopCorner.x + m_TopWidth;
		gVertPool[0].y = m_TopCorner.y;
		gVertPool[0].z = m_TopCorner.z;

		// Back top left
		gVertPool[1].x = m_TopCorner.x;
		gVertPool[1].y = m_TopCorner.y;
		gVertPool[1].z = m_TopCorner.z;

		// Back bottom right
		gVertPool[2].x = position->Point1->x  + m_BottomWidth;
		gVertPool[2].y = position->Point1->y;
		gVertPool[2].z = position->Point1->z;

		// Back bottom left
		gVertPool[3].x = position->Point1->x;
		gVertPool[3].y = position->Point1->y;
		gVertPool[3].z = position->Point1->z;

		// Front top right
		gVertPool[4].x = m_TopCorner.x + m_TopWidth;
		gVertPool[4].y = m_TopCorner.y;
		gVertPool[4].z = m_TopCorner.z + m_TopDepth;

		// Front top left
		gVertPool[5].x = m_TopCorner.x;
		gVertPool[5].y = m_TopCorner.y;
		gVertPool[5].z = m_TopCorner.z + m_TopDepth;

		// Front bottom right
		gVertPool[6].x = position->Point1->x  + m_BottomWidth;
		gVertPool[6].y = position->Point1->y;
		gVertPool[6].z = position->Point1->z + m_BottomDepth;

		// Front bottom left
		gVertPool[7].x = position->Point1->x;
		gVertPool[7].y = position->Point1->y;
		gVertPool[7].z = position->Point1->z + m_BottomDepth;
                
                for(int i = 0; i < vertexCount; ++i)
		{
			gVertPool[i].color = m_color;
			::D3DXVec3Normalize(&gVertPool[i].normal, &gVertPool[i].normal);
		}
		// Indexes for our cube
		WORD indexList[indexCount] = { 0, 2, 3,
							   3, 1, 0,
							   7, 6, 4,
							   4, 5, 7,
							   4, 6, 2, 
							   2, 0, 4,
							   1, 3, 7,
							   7, 5, 1,
							   4, 0, 1,
							   1, 5, 4,
							   2, 6, 7,
							   7, 3, 2 };

		m_pVB = m_d3dobj->getVertexBuffer(gVertPool, vertexCount);
		m_pIB = m_d3dobj->getIndexBuffer(indexList, indexCount);	
	}
	
	return m_d3dobj->RenderBuffered(m_pVB, vertexCount, m_pIB, indexCount);


Sphere code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
if(m_pVB == NULL)
	{
		LPD3DXMESH tempSphere;
		D3DXCreateSphere(m_d3dobj->g_pd3dDevice, 1, 30, 30, &tempSphere, NULL);
		tempSphere->CloneMeshFVF(0, D3DFVF_CUSTOMVERTEX, m_d3dobj->g_pd3dDevice, &meshSphere);
		tempSphere->Release();
		meshSphere->GetVertexBuffer(&m_pVB); // TODO: check return, exceptions
		int nNumVert = meshSphere->GetNumVertices();
		CUSTOMVERTEX * pVertices;
		m_pVB->Lock(0, 0, (void **)&pVertices, 0);
		for (int i = 0; i < nNumVert; ++i)
		{
			// Add some color
			pVertices[i].color = m_Color;
		}
		m_pVB->Unlock();
		m_pVB->Release();
	}

	D3DXMATRIX matrixScale, matrixTranslate, matrixTransform, matrixPrevTransform;
    D3DXMatrixScaling( &matrixScale, m_fRadius, m_fRadius, m_fRadius );
	D3DXMatrixTranslation( &matrixTranslate, position->Point1->x, position->Point1->y, position->Point1->z );
	m_d3dobj->g_pd3dDevice->GetTransform( D3DTS_WORLD, &matrixPrevTransform );
    matrixTransform = matrixScale * matrixTranslate * matrixPrevTransform;	

	m_d3dobj->g_pd3dDevice->SetTransform( D3DTS_WORLD, &matrixTransform );
	//return m_d3dobj->RenderBuffered(m_pVB, meshSphere->GetNumVertices(), m_pIB, meshSphere->GetNumFaces() * 3);
	HRESULT res = meshSphere->DrawSubset(0);
	m_d3dobj->g_pd3dDevice->SetTransform( D3DTS_WORLD, &matrixPrevTransform );
	return res;


Cylinder code; it helps to know the first param is a list of lines, which describe a list of cylinders. Line.P1 is the position of the center of each segment, Line.P2 is basically the up vector. The 2nd param is a list of radii vectors: http://pastebin.com/FkQxVPd0 (running out of space here)

Finally, 'Person' code for lego man: http://pastebin.com/GtPpNYMM

Any thoughts, suggestions, or instruction is greatly appreciated!

--Rollie

Edit: One issue appears to be that d3d scaling operations scale the normals too (seems odd, but okay). There is a setting to normalize normals, which helps with the disparity between the above cylinder and sphere appearances. Things still seem a bit off, but better.
 
myD3D->g_pd3dDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );
Last edited on
Topic archived. No new replies allowed.