Example #1
0
void Cone3D::buildTexCoords(IDirect3DDevice9* gd3dDevice)
{
	D3DVERTEXELEMENT9 elements[64];
	UINT numElements = 0;
	VertexPos::Decl->GetDeclaration(elements, &numElements);

	ID3DXMesh* temp = 0;
	HR(mpMesh->CloneMesh(D3DXMESH_SYSTEMMEM,
		elements, gd3dDevice, &temp));

	ReleaseCOM(mpMesh);

	// Now generate texture coordinates for each vertex.
	VertexPos* vertices = 0;
	HR(temp->LockVertexBuffer(0, (void**)&vertices));

	D3DXVECTOR3 maxPoint(-FLT_MAX, -FLT_MAX, -FLT_MAX);
	D3DXVECTOR3 minPoint(FLT_MAX, FLT_MAX, FLT_MAX);

	for (UINT i = 0; i < temp->GetNumVertices(); ++i)
	{
		D3DXVec3Maximize(&maxPoint, &maxPoint, &vertices[i].mPos);
		D3DXVec3Minimize(&minPoint, &minPoint, &vertices[i].mPos);
	}

	float a = minPoint.z;
	float b = maxPoint.z;
	float h = b - a;

	for (int i = 0; i < (int)temp->GetNumVertices(); i++)
	{
		float x = vertices[i].mPos.x;
		float y = vertices[i].mPos.z;
		float z = vertices[i].mPos.y;

		float theta = atan2f(z, x);
		float y2 = y - b;

		float u = theta / (2.0f * D3DX_PI);
		float v = y2 / -h;

		vertices[i].mTexCoord.x = u;
		vertices[i].mTexCoord.y = v;
	}

	HR(temp->UnlockVertexBuffer());

	HR(temp->CloneMesh(D3DXMESH_MANAGED | D3DXMESH_WRITEONLY,
		elements, gd3dDevice, &mpMesh));

	ReleaseCOM(temp);
}
Example #2
0
void CMesh3D::DrawMyMesh()
{
	D3DXMATRIX  wvp;
	if ( m_pMesh )
	{
		wvp = m_MatrixWorld * m_MatrixView * m_MatrixProjection;
		if ( g_DeviceD3D.m_pConstTableVS[Diffuse] )
		{
			g_DeviceD3D.m_pConstTableVS[Diffuse] -> SetMatrix( g_pD3DDevice, "mat_mvp",   &wvp );
			g_DeviceD3D.m_pConstTableVS[Diffuse] -> SetMatrix( g_pD3DDevice, "mat_world", &m_MatrixWorld );
			g_DeviceD3D.m_pConstTableVS[Diffuse] -> SetVector( g_pD3DDevice, "vec_light", &Light );
			g_DeviceD3D.m_pConstTablePS[Diffuse] -> SetFloat(  g_pD3DDevice, "diffuse_intensity", Diffuse_intensity );	
			g_DeviceD3D.m_pConstTablePS[Diffuse] -> SetFloat(  g_pD3DDevice, "Alpha", m_Alpha );	
		}
		// устанавливаем шейдеры
		g_pD3DDevice->SetVertexShader( g_DeviceD3D.m_pVertexShader[Diffuse] );
		g_pD3DDevice->SetPixelShader(  g_DeviceD3D.m_pPixelShader [Diffuse] );

		g_pD3DDevice->SetStreamSource( 0, m_VertexBuffer, 0, m_SizeFVF );
		g_pD3DDevice->SetIndices( m_IndexBuffer );
		for ( int i = 0; i < m_TexturCount; ++i )
		{
			g_pD3DDevice -> SetMaterial( &m_pMeshMaterial[i] );
			g_pD3DDevice -> SetTexture( 0, m_pMeshTextura[i] );
			//m_pMesh -> DrawSubset(i);
		}
		g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, m_pMesh->GetNumVertices(), 0, m_pMesh->GetNumFaces() ); 
	}
}
void AmbientDiffuseDemo::updateScene(float dt)
{
	mGfxStats->setVertexCount(mTeapot->GetNumVertices());
	mGfxStats->setTriCount(mTeapot->GetNumFaces());
	mGfxStats->update(dt);

	// Get snapshot of input devices.
	gDInput->poll();

	// Check input.
	if( gDInput->keyDown(DIK_W) )	 
		mCameraHeight   += 25.0f * dt;
	if( gDInput->keyDown(DIK_S) )	 
		mCameraHeight   -= 25.0f * dt;

	// Divide by 50 to make mouse less sensitive. 
	mCameraRotationY += gDInput->mouseDX() / 100.0f;
	mCameraRadius    += gDInput->mouseDY() / 25.0f;

	// If we rotate over 360 degrees, just roll back to 0
	if( fabsf(mCameraRotationY) >= 2.0f * D3DX_PI ) 
		mCameraRotationY = 0.0f;

	// Don't let radius get too small.
	if( mCameraRadius < 5.0f )
		mCameraRadius = 5.0f;

	// The camera position/orientation relative to world space can 
	// change every frame based on input, so we need to rebuild the
	// view matrix every frame with the latest changes.
	buildViewMtx();
}
Example #4
0
void AmbientDiffuseDemo::updateScene(float dt)
{
    mGfxStats->setVertexCount(mTeapot->GetNumVertices());
    mGfxStats->setTriCount(mTeapot->GetNumFaces());
    mGfxStats->update(dt);

    gDInput->poll();

    if (gDInput->keyDown(DIK_W))
        mCameraHeight += 25.0f * dt;
    if (gDInput->keyDown(DIK_S))
        mCameraHeight -= 25.0f * dt;

    // divide by 50 to make mouse less sensitive
    mCameraRotationY += gDInput->mouseDX() / 50.0f;
    mCameraRadius    += gDInput->mouseDY() / 50.0f;

    if (fabsf(mCameraRotationY) >= 2.0f * D3DX_PI)
        mCameraRotationY = 0.0f;

    if (mCameraRadius < 5.0f)
        mCameraRadius = 5.0f;

    buildViewMtx();
}
Example #5
0
BOOL RenderPick::Init(UINT width, UINT height, HWND hwnd, BOOL windowed, D3DDEVTYPE devType) {
    HRESULT hr = Render::Init(width, height, hwnd, windowed, devType);
    SGL_FAILED_DO(hr, MYTRACE_DX("Render::Init", hr); return FALSE);

    // Create the teapot.
    ID3DXMesh* teapot;
    D3DXCreateTeapot(m_D3DDev, &teapot, NULL);
    m_Teapot.Attach(teapot);

    // Compute the bounding sphere.
    BYTE* v = 0;
    teapot->LockVertexBuffer(0, (void**) &v);

    D3DXComputeBoundingSphere((D3DXVECTOR3*) v, teapot->GetNumVertices(), D3DXGetFVFVertexSize(teapot->GetFVF()), &m_BSphere.center, &m_BSphere.radius);
    teapot->UnlockVertexBuffer();

    // Build a sphere mesh that describes the teapot's bounding sphere.
    ID3DXMesh* sphere;
    D3DXCreateSphere(m_D3DDev, m_BSphere.radius, 20, 20, &sphere, NULL);
    m_Sphere.Attach(sphere);

    // Set light.
    D3DXVECTOR3 dir(0.707f, -0.0f, 0.707f);
    D3DXCOLOR clr(1.0f, 1.0f, 1.0f, 1.0f);
    D3DLIGHT9 light;
    SGL::InitDirLight(&light, dir, clr);

    m_D3DDev->SetLight(0, &light);
    m_D3DDev->LightEnable(0, TRUE);
    m_D3DDev->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
    m_D3DDev->SetRenderState(D3DRS_SPECULARENABLE, FALSE);

    // Set view matrix.
    D3DXVECTOR3 pos(0.0f, 0.0f, -10.0f);
    D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

    D3DXMATRIX V;
    D3DXMatrixLookAtLH(&V, &pos, &target, &up);
    m_D3DDev->SetTransform(D3DTS_VIEW, &V);

    // Set projection matrix.
    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.25f, (float) width / (float) height, 1.0f, 1000.0f);
    m_D3DDev->SetTransform(D3DTS_PROJECTION, &proj);

    // Setup a basic scene.
    m_BasicScene.reset(new BasicScene(m_D3DDev));
    if (!m_BasicScene->Init())
        return FALSE;

    if (!InitFont())
        return FALSE;

    return TRUE;
}
Example #6
0
void SolarSysDemo::genSphericalTexCoords()
{
	// D3DXCreate* functions generate vertices with position 
	// and normal data.  But for texturing, we also need
	// tex-coords.  So clone the mesh to change the vertex
	// format to a format with tex-coords.

	D3DVERTEXELEMENT9 elements[64];
	UINT numElements = 0;
	VertexPNT::Decl->GetDeclaration(elements, &numElements);

	ID3DXMesh* temp = 0;
	HR(mSphere->CloneMesh(D3DXMESH_SYSTEMMEM, 
		elements, gd3dDevice, &temp));

	ReleaseCOM(mSphere);

	// Now generate texture coordinates for each vertex.
	VertexPNT* vertices = 0;
	HR(temp->LockVertexBuffer(0, (void**)&vertices));

	for(UINT i = 0; i < temp->GetNumVertices(); ++i)
	{
		// Convert to spherical coordinates.
		D3DXVECTOR3 p = vertices[i].pos;
	
 
		float theta = atan2f(p.z, p.x);
		float phi   = acosf(p.y / sqrtf(p.x*p.x+p.y*p.y+p.z*p.z));

		// Phi and theta give the texture coordinates, but are not in 
		// the range [0, 1], so scale them into that range.

		float u = theta / (2.0f*D3DX_PI);
		float v = phi   / D3DX_PI;
		
		// Save texture coordinates.
		
		vertices[i].tex0.x = u;
		vertices[i].tex0.y = v;
	}
	HR(temp->UnlockVertexBuffer());

	// Clone back to a hardware mesh.
	HR(temp->CloneMesh(D3DXMESH_MANAGED | D3DXMESH_WRITEONLY,
		elements, gd3dDevice, &mSphere));

	ReleaseCOM(temp);
}
Example #7
0
void MeshX::BuildSkinnedMesh()
{
	ID3DXMesh* oldMesh = allocMeshHierarchy.GetMeshList().front()->MeshData.pMesh;

	//compute normal
	D3DVERTEXELEMENT9 elements[MAX_FVF_DECL_SIZE];
	oldMesh->GetDeclaration(elements);

	ID3DXMesh* tempMesh = 0;
	ID3DXMesh* tempOpMesh = 0;
	oldMesh->CloneMesh(D3DXMESH_SYSTEMMEM, elements, pDevice, &tempMesh);
	 
	if( !HasNormals(tempMesh) )
		D3DXComputeNormals(tempMesh, 0);

	//optimize the mesh
	DWORD* adj = new DWORD[tempMesh->GetNumFaces()*3];
	ID3DXBuffer* remap = 0;
	tempMesh->GenerateAdjacency(0.00001f, adj);
	tempMesh->Optimize(D3DXMESH_SYSTEMMEM | D3DXMESHOPT_VERTEXCACHE | 
		D3DXMESHOPT_ATTRSORT, adj, 0, 0, &remap, &tempOpMesh);

	SafeRelease(tempMesh);

	// In the .X file (specifically the array DWORD vertexIndices[nWeights]
	// data member of the SkinWeights template) each bone has an array of
	// indices which identify the vertices of the mesh that the bone influences.
	// Because we have just rearranged the vertices (from optimizing), the vertex 
	// indices of a bone are obviously incorrect (i.e., they index to vertices the bone
	// does not influence since we moved vertices around).  In order to update a bone's 
	// vertex indices to the vertices the bone _does_ influence, we simply need to specify
	// where we remapped the vertices to, so that the vertex indices can be updated to 
	// match.  This is done with the ID3DXSkinInfo::Remap method.
	skinInfo->Remap(tempOpMesh->GetNumVertices(), 
		(DWORD*)remap->GetBufferPointer());
	SafeRelease(remap); // Done with remap info.

	DWORD        numBoneComboEntries = 0;
	ID3DXBuffer* boneComboTable      = 0;
	DWORD maxVertInfluences;
	skinInfo->ConvertToIndexedBlendedMesh(tempOpMesh, 0,  
		128, 0, 0, 0, 0, &maxVertInfluences,
		&numBoneComboEntries, &boneComboTable, &this->mesh);

	SafeRelease(tempOpMesh);
	SafeRelease(boneComboTable);
	delete[] adj;
}
/** Merges a set of D3DXMeshes. */
static void MergeD3DXMeshes(
	IDirect3DDevice9* Device,
	TRefCountPtr<ID3DXMesh>& OutMesh,TArray<int32>& OutBaseFaceIndex,const TArray<ID3DXMesh*>& Meshes)
{
	TArray<D3DVERTEXELEMENT9> VertexElements;
	GetD3D9MeshVertexDeclarations(VertexElements);
		
	// Count the number of faces and vertices in the input meshes.
	int32 NumFaces = 0;
	int32 NumVertices = 0;
	for(int32 MeshIndex = 0;MeshIndex < Meshes.Num();MeshIndex++)
	{
		NumFaces += Meshes[MeshIndex]->GetNumFaces();
		NumVertices += Meshes[MeshIndex]->GetNumVertices();
	}

	// Create mesh for source data
	VERIFYD3D9RESULT(D3DXCreateMesh(
		NumFaces,
		NumVertices,
		D3DXMESH_SYSTEMMEM,
		(D3DVERTEXELEMENT9*)VertexElements.GetData(),
		Device,
		OutMesh.GetInitReference()
		) );

	// Fill D3DXMesh
	FUtilVertex* ResultVertices;
	uint16*		 ResultIndices;
	::DWORD *		 ResultAttributes;
	OutMesh->LockVertexBuffer(0,(LPVOID*)&ResultVertices);
	OutMesh->LockIndexBuffer(0,(LPVOID*)&ResultIndices);
	OutMesh->LockAttributeBuffer(0, &ResultAttributes);

	int32 BaseVertexIndex = 0;
	int32 BaseFaceIndex = 0;
	for(int32 MeshIndex = 0;MeshIndex < Meshes.Num();MeshIndex++)
	{
		ID3DXMesh* Mesh = Meshes[MeshIndex];
				
		FUtilVertex* Vertices;
		uint16*		 Indices;
		::DWORD *		 Attributes;
		Mesh->LockVertexBuffer(0,(LPVOID*)&Vertices);
		Mesh->LockIndexBuffer(0,(LPVOID*)&Indices);
		Mesh->LockAttributeBuffer(0, &Attributes);

		for(uint32 FaceIndex = 0;FaceIndex < Mesh->GetNumFaces();FaceIndex++)
		{
			for(uint32 VertexIndex = 0;VertexIndex < 3;VertexIndex++)
			{
				*ResultIndices++ = BaseVertexIndex + *Indices++;
			}
		}
		OutBaseFaceIndex.Add(BaseFaceIndex);
		BaseFaceIndex += Mesh->GetNumFaces();

		FMemory::Memcpy(ResultVertices,Vertices,Mesh->GetNumVertices() * sizeof(FUtilVertex));
		ResultVertices += Mesh->GetNumVertices();
		BaseVertexIndex += Mesh->GetNumVertices();

		FMemory::Memcpy(ResultAttributes,Attributes,Mesh->GetNumFaces() * sizeof(uint32));
		ResultAttributes += Mesh->GetNumFaces();

		Mesh->UnlockIndexBuffer();
		Mesh->UnlockVertexBuffer();
		Mesh->UnlockAttributeBuffer();
	}

	OutMesh->UnlockIndexBuffer();
	OutMesh->UnlockVertexBuffer();
	OutMesh->UnlockAttributeBuffer();
}
Example #9
0
HRESULT HelloShadowVolume::RestoreDeviceObjects()
{
    HRESULT hr;
    IDirect3DDevice8* device;
    hr = m_spD3D->CreateDevice(
             D3DADAPTER_DEFAULT,
             D3DDEVTYPE_HAL,
             m_hWnd,
             D3DCREATE_HARDWARE_VERTEXPROCESSING,
             &m_dpps,
             &device);
    if (FAILED(hr))
    {
        MessageBox(0, L"CreateDevice failed", 0, 0);
        return E_FAIL;
    }
    m_spDevice.reset(device, [](IDirect3DDevice8* device) {
        device->Release();
    });

    m_spDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
    m_spDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    m_spDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
    D3DVIEWPORT8 viewport = { 0, 0, m_iWidth, m_iHeight };
    m_spDevice->SetViewport(&viewport);

    D3DXVECTOR3 eye(0.0f, 0.0f, 30.0f);
    D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    D3DXMatrixLookAtLH(&m_mtView, &eye, &target, &up);

    D3DXMatrixPerspectiveFovLH(&m_mtProj, 0.2*D3DX_PI, (float)m_iWidth / (float)m_iHeight, 1.0f, 100.f);

    m_cPlaneTint = { 0.7f, 0.6f, 0.4f, 1.0f };


    ID3DXMesh* plane;
    //D3DXCreatePolygon(m_spDevice.get(), 2.0f, 4, &plane, NULL);
    CreatePlane(m_spDevice.get(), 15.0f, 10, &plane);
    //D3DXCreateSphere(m_spDevice.get(), 1.0f,20,20, &plane, NULL);

    IDirect3DVertexBuffer8* vb;
    IDirect3DIndexBuffer8* ib;
    plane->GetVertexBuffer(&vb);
    plane->GetIndexBuffer(&ib);
    m_spPlaneVB.reset(vb, [](IDirect3DVertexBuffer8* vb) {
        vb->Release();
    });
    m_spPlaneIB.reset(ib, [](IDirect3DIndexBuffer8* ib) {
        ib->Release();
    });
    m_dwPlaneNumVertices = plane->GetNumVertices();
    m_dwPlaneNumFaces = plane->GetNumFaces();

    plane->Release();

    DWORD decl[] = {
        D3DVSD_STREAM(0),
        D3DVSD_REG(0, D3DVSDT_FLOAT3),
        D3DVSD_REG(3, D3DVSDT_FLOAT3),
        D3DVSD_END()
    };
    hr = CreateVSFromBinFile(m_spDevice.get(), decl, L"plane.vso", &m_dwPlaneVSH);
    if (FAILED(hr))
    {
        MessageBox(0, 0, L"CreateVSFromBinFile failed", 0);
        return E_FAIL;
    }
    hr = CreatePSFromBinFile(m_spDevice.get(), L"plane.pso", &m_dwPlanePSH);
    if (FAILED(hr))
    {
        MessageBox(0, 0, L"CreatePSFromBinFile failed", 0);
        return E_FAIL;
    }

    D3DXMATRIX Rx, Tz;
    D3DXMatrixRotationX(&Rx, D3DX_PI*0.5f);
    D3DXMatrixTranslation(&Tz, 0.0f, -3.0f, 0.0f);
    m_mtPlaneWorld = Rx * Tz;

    ID3DXMesh* occluder;
    CreateOccluder(m_spDevice.get(), &occluder);
    IDirect3DVertexBuffer8* vbOccluder;
    IDirect3DIndexBuffer8* ibOccluder;
    occluder->GetVertexBuffer(&vbOccluder);
    occluder->GetIndexBuffer(&ibOccluder);
    m_spOccluderVB.reset(vbOccluder, [](IDirect3DVertexBuffer8* vb) {
        vb->Release();
    });
    m_spOccluderIB.reset(ibOccluder, [](IDirect3DIndexBuffer8* ib) {
        ib->Release();
    });
    m_dwOccluderNumVertices = occluder->GetNumVertices();
    m_dwOccluderNumFaces = occluder->GetNumFaces();
    occluder->Release();

    hr = CreateVSFromBinFile(m_spDevice.get(), decl, L"occluder.vso", &m_dwOccluderVSH);
    if (FAILED(hr))
    {
        MessageBox(0, 0, L"CreateVSFromBinFile failed", 0);
        return E_FAIL;
    }
    hr = CreatePSFromBinFile(m_spDevice.get(), L"occluder.pso", &m_dwOccluderPSH);
    if (FAILED(hr))
    {
        MessageBox(0, 0, L"CreatePSFromBinFile failed", 0);
        return E_FAIL;
    }
    m_cOccluderTint = { 0.3f, 0.0f, 0.8f, 1.0f };
    D3DXMATRIX Rz, T;
    D3DXMatrixTranslation(&T, 5.1f * cosf(0.5), 0.0f, 5.1f * sinf(0.5));
    D3DXMatrixIdentity(&m_mtVolumeWorld);
    D3DXMatrixRotationZ(&Rz, 0.5f);
    m_mtOccluderWorld = T * Rz;

    ID3DXMesh* volume;
    CreateVolume(m_spDevice.get(), &volume);
    IDirect3DVertexBuffer8* vbVolume;
    IDirect3DIndexBuffer8* ibVolume;
    volume->GetVertexBuffer(&vbVolume);
    volume->GetIndexBuffer(&ibVolume);
    m_spVolumeVB.reset(vbVolume, [](IDirect3DVertexBuffer8* vb) {
        vb->Release();
    });
    m_spVolumeIB.reset(ibVolume, [](IDirect3DIndexBuffer8* ib) {
        ib->Release();
    });
    m_dwVolumeNumVertices = volume->GetNumVertices();
    m_dwVolumeNumFaces = volume->GetNumFaces();
    volume->Release();

    hr = CreateVSFromBinFile(m_spDevice.get(), decl, L"volume.vso", &m_dwVolumeVSH);
    if (FAILED(hr))
    {
        MessageBox(0, 0, L"CreateVSFromBinFile failed", 0);
        return E_FAIL;
    }
    hr = CreatePSFromBinFile(m_spDevice.get(), L"volume.pso", &m_dwVolumePSH);
    if (FAILED(hr))
    {
        MessageBox(0, 0, L"CreatePSFromBinFile failed", 0);
        return E_FAIL;
    }
    m_cVolumeTint = { 0.7f, 0.0f, 0.0f, 1.0f };

    D3DXMATRIX Sx;
    D3DXMatrixIdentity(&m_mtVolumeWorld);
    D3DXMatrixScaling(&Sx, 6.0f, 1.0f, 1.0f);
    D3DXMatrixRotationZ(&Rz, 0.5f);
    m_mtVolumeWorld = Sx * Rz;

    return S_OK;
}
Example #10
0
void Terrain::buildSubGridMesh(RECT& R, VertexPNT* gridVerts)
{
	//===============================================================
	// Create the subgrid mesh.
	ID3DXMesh* subMesh = 0;
	D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
	UINT numElems = 0;
	HR(VertexPNT::Decl->GetDeclaration(elems, &numElems));
	HR(D3DXCreateMesh(SubGrid::NUM_TRIS, SubGrid::NUM_VERTS, 
		D3DXMESH_MANAGED, elems, gd3dDevice, &subMesh));


	//===============================================================
	// Build Vertex Buffer.  Copy rectangle of vertices from the
	// grid into the subgrid structure.
	VertexPNT* v = 0;
	HR(subMesh->LockVertexBuffer(0, (void**)&v));
	int k = 0;
	for(int i = R.top; i <= R.bottom; ++i)
	{
		for(int j = R.left; j <= R.right; ++j)
		{
			v[k++] = gridVerts[i*mVertCols+j];
		}
	}

	//===============================================================
	// Compute the bounding box before unlocking the vertex buffer.
	AABB bndBox;
	HR(D3DXComputeBoundingBox((D3DXVECTOR3*)v, subMesh->GetNumVertices(), 
		sizeof(VertexPNT), &bndBox.minPt, &bndBox.maxPt));

	HR(subMesh->UnlockVertexBuffer());


	//===============================================================
	// Build Index and Attribute Buffer.
	// Get indices for subgrid (we don't use the verts here--the verts
	// are given by the parameter gridVerts).
	std::vector<D3DXVECTOR3> tempVerts;
	std::vector<DWORD> tempIndices;
	GenTriGrid(SubGrid::NUM_ROWS, SubGrid::NUM_COLS, mDX, mDZ, 
		D3DXVECTOR3(0.0f, 0.0f, 0.0f), tempVerts, tempIndices);

	WORD* indices  = 0;
	DWORD* attBuff = 0;
	HR(subMesh->LockIndexBuffer(0, (void**)&indices));
	HR(subMesh->LockAttributeBuffer(0, &attBuff));
	for(int i = 0; i < SubGrid::NUM_TRIS; ++i)
	{
		indices[i*3+0] = (WORD)tempIndices[i*3+0];
		indices[i*3+1] = (WORD)tempIndices[i*3+1];
		indices[i*3+2] = (WORD)tempIndices[i*3+2];

		attBuff[i] = 0; // All in subset 0.
	}
	HR(subMesh->UnlockIndexBuffer());
	HR(subMesh->UnlockAttributeBuffer());


	//===============================================================
	// Optimize for the vertex cache and build attribute table.
	DWORD* adj = new DWORD[subMesh->GetNumFaces()*3];
	HR(subMesh->GenerateAdjacency(EPSILON, adj));
	HR(subMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE|D3DXMESHOPT_ATTRSORT,
		adj, 0, 0, 0));
	delete[] adj;

	
	//===============================================================
	// Save the mesh and bounding box.
	mSubGridMeshes.push_back(subMesh);
	mSubGridBndBoxes.push_back(bndBox);
}
Example #11
0
void Terrain::buildGeometry()
{
	//===============================================================
	// Create one large mesh for the grid in system memory.

	DWORD numTris  = (mVertRows-1)*(mVertCols-1)*2;
	DWORD numVerts = mVertRows*mVertCols;

	ID3DXMesh* mesh = 0;
	D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
	UINT numElems = 0;
	HR(VertexPNT::Decl->GetDeclaration(elems, &numElems));
	HR(D3DXCreateMesh(numTris, numVerts, 
		D3DXMESH_SYSTEMMEM|D3DXMESH_32BIT, elems, gd3dDevice, &mesh));


	//===============================================================
	// Write the grid vertices and triangles to the mesh.

	VertexPNT* v = 0;
	HR(mesh->LockVertexBuffer(0, (void**)&v));
	
	std::vector<D3DXVECTOR3> verts;
	std::vector<DWORD> indices;
	GenTriGrid(mVertRows, mVertCols, mDX, mDZ, D3DXVECTOR3(0.0f, 0.0f, 0.0f), verts, indices);

	float w = mWidth;
	float d = mDepth;
	for(UINT i = 0; i < mesh->GetNumVertices(); ++i)
	{
		// We store the grid vertices in a linear array, but we can
		// convert the linear array index to an (r, c) matrix index.
		int r = i / mVertCols;
		int c = i % mVertCols;

		v[i].pos   = verts[i];
		v[i].pos.y = mHeightmap(r, c);

		v[i].tex0.x = (v[i].pos.x + (0.5f*w)) / w;
		v[i].tex0.y = (v[i].pos.z - (0.5f*d)) / -d;
	}

	// Write triangle data so we can compute normals.

	DWORD* indexBuffPtr = 0;
	HR(mesh->LockIndexBuffer(0, (void**)&indexBuffPtr));
	for(UINT i = 0; i < mesh->GetNumFaces(); ++i)
	{
		indexBuffPtr[i*3+0] = indices[i*3+0];
		indexBuffPtr[i*3+1] = indices[i*3+1];
		indexBuffPtr[i*3+2] = indices[i*3+2];
	}
	HR(mesh->UnlockIndexBuffer());

	// Compute Vertex Normals.
	HR(D3DXComputeNormals(mesh, 0));

	
	//===============================================================
	// Now break the grid up into subgrid meshes.

	// Find out the number of subgrids we'll have.  For example, if
	// m = 513, n = 257, SUBGRID_VERT_ROWS = SUBGRID_VERT_COLS = 33,
	// then subGridRows = 512/32 = 16 and sibGridCols = 256/32 = 8.
	int subGridRows = (mVertRows-1) / (SubGrid::NUM_ROWS-1);
	int subGridCols = (mVertCols-1) / (SubGrid::NUM_COLS-1);

	for(int r = 0; r < subGridRows; ++r)
	{
		for(int c = 0; c < subGridCols; ++c)
		{
			// Rectangle that indicates (via matrix indices ij) the
			// portion of global grid vertices to use for this subgrid.
			RECT R = 
			{
					c * (SubGrid::NUM_COLS-1),
					r * (SubGrid::NUM_ROWS-1),
				(c+1) * (SubGrid::NUM_COLS-1),
				(r+1) * (SubGrid::NUM_ROWS-1)
			};

			buildSubGridMesh(R, v); 
		}
	}

	HR(mesh->UnlockVertexBuffer());

	ReleaseCOM(mesh); // Done with global mesh.
}
Example #12
0
void SkinnedMesh::buildSkinnedMesh(ID3DXMesh* mesh)
{
    //====================================================================
    // First add a normal component and 2D texture coordinates component.

    D3DVERTEXELEMENT9 elements[64];
    UINT numElements = 0;
    VertexPNT::Decl->GetDeclaration(elements, &numElements);

    ID3DXMesh* tempMesh = 0;
    HR(mesh->CloneMesh(D3DXMESH_SYSTEMMEM, elements, gd3dDevice, &tempMesh));

    if( !hasNormals(tempMesh) )
        HR(D3DXComputeNormals(tempMesh, 0));

    //====================================================================
    // Optimize the mesh; in particular, the vertex cache.
    DWORD* adj = new DWORD[tempMesh->GetNumFaces()*3];
    ID3DXBuffer* remap = 0;
    HR(tempMesh->GenerateAdjacency(EPSILON, adj));
    ID3DXMesh* optimizedTempMesh = 0;
    HR(tempMesh->Optimize(D3DXMESH_SYSTEMMEM | D3DXMESHOPT_VERTEXCACHE |
                          D3DXMESHOPT_ATTRSORT, adj, 0, 0, &remap, &optimizedTempMesh));

    ReleaseCOM(tempMesh); // Done w/ this mesh.
    delete[] adj;         // Done with buffer.

    // In the .X file (specifically the array DWORD vertexIndices[nWeights]
    // data member of the SkinWeights template) each bone has an array of
    // indices which identify the vertices of the mesh that the bone influences.
    // Because we have just rearranged the vertices (from optimizing), the vertex
    // indices of a bone are obviously incorrect (i.e., they index to vertices the bone
    // does not influence since we moved vertices around).  In order to update a bone's
    // vertex indices to the vertices the bone _does_ influence, we simply need to specify
    // where we remapped the vertices to, so that the vertex indices can be updated to
    // match.  This is done with the ID3DXSkinInfo::Remap method.
    HR(mSkinInfo->Remap(optimizedTempMesh->GetNumVertices(),
                        (DWORD*)remap->GetBufferPointer()));
    ReleaseCOM(remap); // Done with remap info.

    //====================================================================
    // The vertex format of the source mesh does not include vertex weights
    // nor bone index data, which are both needed for vertex blending.
    // Therefore, we must convert the source mesh to an "indexed-blended-mesh,"
    // which does have the necessary data.

    DWORD        numBoneComboEntries = 0;
    ID3DXBuffer* boneComboTable      = 0;
    HR(mSkinInfo->ConvertToIndexedBlendedMesh(optimizedTempMesh, D3DXMESH_MANAGED | D3DXMESH_WRITEONLY,
            MAX_NUM_BONES_SUPPORTED, 0, 0, 0, 0, &mMaxVertInfluences,
            &numBoneComboEntries, &boneComboTable, &mSkinnedMesh));

    ReleaseCOM(optimizedTempMesh); // Done with tempMesh.
    ReleaseCOM(boneComboTable); // Don't need bone table.

#if defined(DEBUG) | defined(_DEBUG)
    // Output to the debug output the vertex declaration of the mesh at this point.
    // This is for insight only to see what exactly ConvertToIndexedBlendedMesh
    // does to the vertex declaration.
    D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
    HR(mSkinnedMesh->GetDeclaration(elems));

    OutputDebugString("\nVertex Format After ConvertToIndexedBlendedMesh\n");
    int i = 0;
    while( elems[i].Stream != 0xff ) // While not D3DDECL_END()
    {
        if( elems[i].Type == D3DDECLTYPE_FLOAT1)
            OutputDebugString("Type = D3DDECLTYPE_FLOAT1; ");
        if( elems[i].Type == D3DDECLTYPE_FLOAT2)
            OutputDebugString("Type = D3DDECLTYPE_FLOAT2; ");
        if( elems[i].Type == D3DDECLTYPE_FLOAT3)
            OutputDebugString("Type = D3DDECLTYPE_FLOAT3; ");
        if( elems[i].Type == D3DDECLTYPE_UBYTE4)
            OutputDebugString("Type = D3DDECLTYPE_UBYTE4; ");

        if( elems[i].Usage == D3DDECLUSAGE_POSITION)
            OutputDebugString("Usage = D3DDECLUSAGE_POSITION\n");
        if( elems[i].Usage == D3DDECLUSAGE_BLENDWEIGHT)
            OutputDebugString("Usage = D3DDECLUSAGE_BLENDWEIGHT\n");
        if( elems[i].Usage == D3DDECLUSAGE_BLENDINDICES)
            OutputDebugString("Usage = D3DDECLUSAGE_BLENDINDICES\n");
        if( elems[i].Usage == D3DDECLUSAGE_NORMAL)
            OutputDebugString("Usage = D3DDECLUSAGE_NORMAL\n");
        if( elems[i].Usage == D3DDECLUSAGE_TEXCOORD)
            OutputDebugString("Usage = D3DDECLUSAGE_TEXCOORD\n");
        ++i;
    }
#endif
}
bool CMeshBundle::loadMesh( const CResourceId& id, const CResourceId& fullName, CMesh& mesh ) const
{
	// try to load with D3DX
	// obsolete case: .X files
	if( CStringHelper::endsWith( fullName.getUniqueName(), ".x" ) || CStringHelper::endsWith( fullName.getUniqueName(), ".X" ) ) {
		ID3DXBuffer* adjancency = NULL;
		ID3DXBuffer* material = NULL;
		ID3DXBuffer* effects = NULL;
		DWORD matCount;
		ID3DXMesh* dxmesh = NULL;

		HRESULT hres = D3DXLoadMeshFromX(
			fullName.getUniqueName().c_str(),
			D3DXMESH_SYSTEMMEM,
			&CD3DDevice::getInstance().getDevice(),
			&adjancency,
			&material,
			&effects,
			&matCount,
			&dxmesh );
		if( !SUCCEEDED( hres ) )
			return false;
		assert( dxmesh );

		if( adjancency )
			adjancency->Release();
		if( material )
			material->Release();
		if( effects )
			effects->Release();

		//
		// init our mesh

		assert( !mesh.isCreated() );
		// HACK - very limited
		int formatFlags = 0;
		DWORD dxFormat = dxmesh->GetFVF();
		if( dxFormat & D3DFVF_XYZ )
			formatFlags |= CVertexFormat::V_POSITION;
		if( dxFormat & D3DFVF_NORMAL )
			formatFlags |= CVertexFormat::V_NORMAL;
		if( dxFormat & D3DFVF_TEX1 )
			formatFlags |= CVertexFormat::V_UV0_2D;
		CVertexFormat vertFormat( formatFlags );
		// HACK
		int indexStride = 2;

		CD3DVertexDecl* vertDecl = RGET_VDECL( CVertexDesc( vertFormat ) );
		mesh.createResource( dxmesh->GetNumVertices(), dxmesh->GetNumFaces()*3, vertFormat, indexStride, *vertDecl, CMesh::BUF_STATIC );

		//
		// now, copy data into our mesh

		void *dxvb, *dxib;
		dxmesh->LockVertexBuffer( 0, &dxvb );
		dxmesh->LockIndexBuffer( 0, &dxib );
		void* myvb = mesh.lockVBWrite();
		void* myib = mesh.lockIBWrite();

		memcpy( myvb, dxvb, mesh.getVertexCount() * mesh.getVertexStride() );
		memcpy( myib, dxib, mesh.getIndexCount() * mesh.getIndexStride() );
		
		dxmesh->UnlockVertexBuffer();
		dxmesh->UnlockIndexBuffer();
		mesh.unlockVBWrite();
		mesh.unlockIBWrite();

		//
		// create groups

		int ngroups;
		dxmesh->GetAttributeTable( 0, (DWORD*)&ngroups );
		D3DXATTRIBUTERANGE *attrs = new D3DXATTRIBUTERANGE[ngroups];
		dxmesh->GetAttributeTable( attrs, (DWORD*)&ngroups );
		for( int i = 0; i < ngroups; ++i ) {
			const D3DXATTRIBUTERANGE& a = attrs[i];
			mesh.addGroup( CMesh::CGroup( a.VertexStart, a.VertexCount, a.FaceStart, a.FaceCount ) );
		}
		delete[] attrs;

		// release d3dx mesh
		dxmesh->Release();

	} else {

		// our own format
		assert( !mesh.isCreated() );
		bool ok = CMeshSerializer::loadMeshFromFile( fullName.getUniqueName().c_str(), mesh );
		if( !ok )
			return false;
	}
	mesh.computeAABBs();
	CONSOLE.write( "mesh loaded '" + id.getUniqueName() + "'" );
	return true;
}
Example #14
0
VCNNode* D3DConverter::ConvertMesh(const std::wstring& name, LPD3DXMESHCONTAINER baseMeshContainer,
	D3DXFRAME* frameRoot, ID3DXAnimationController* animController, LPDIRECT3DDEVICE9 device)
{
	MultiAnimMC* meshContainer = static_cast<MultiAnimMC*>(baseMeshContainer);
	ID3DXMesh* systemMesh = meshContainer->MeshData.pMesh;

	// Load vertex caches
	//
	DWORD meshFVF = systemMesh->GetFVF();
	size_t vertexCount = systemMesh->GetNumVertices();
	const DWORD stride = D3DXGetFVFVertexSize( meshFVF );
	const DWORD normalStride = D3DXGetFVFVertexSize( D3DFVF_NORMAL );
	const DWORD diffuseStride = D3DXGetFVFVertexSize( D3DFVF_DIFFUSE );
	const DWORD textureStride = D3DXGetFVFVertexSize( D3DFVF_TEX1 );

	std::vector<VCNFloat> vtPositionBuffer( vertexCount * kCacheStrides[VT_POSITION] );
	std::vector<VCNFloat> vtBlendWeights( vertexCount * kCacheStrides[VT_BLENDWEIGHTS] ); //TODO Verify the size of this shit
	std::vector<DWORD> vtBlendIndices( vertexCount * kCacheStrides[VT_BLENDINDICES] ); //TODO Verify the size of this shit

	std::vector<VCNFloat> vtNormalBuffer( vertexCount * kCacheStrides[VT_LIGHTING] );
	std::vector<VCNFloat> vtTextureBuffer( vertexCount * kCacheStrides[VT_DIFFUSE_TEX_COORDS] );

	VCNFloat* vtPositionBuf = &vtPositionBuffer[0];
	VCNFloat* vtBlendWeightBuf = &vtBlendWeights[0];
	DWORD* vtBlendIndicesBuf = &vtBlendIndices[0];

	VCNFloat* vtNormalBuf = &vtNormalBuffer[0];
	VCNFloat* vtTextureBuf = &vtTextureBuffer[0];

	BYTE* vbptr = NULL;
	BYTE* vblineptr = NULL;
	systemMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&vblineptr);

	DWORD positionBlendAndIndicesStride = GetPositionStride(meshFVF);

	for(VCNUInt i = 0; i < vertexCount; ++i)
	{
		vbptr = vblineptr;

		if ( ContainsPositionInformation(meshFVF) )
		{
			// Read position
			float* posData = (float*)vbptr;
			*vtPositionBuf = posData[0]; vtPositionBuf++;
			*vtPositionBuf = posData[1]; vtPositionBuf++;
			*vtPositionBuf = posData[2]; vtPositionBuf++;

			if (ContainsBlending(meshFVF))
			{
				// Get blend weights
				size_t blendCount = (positionBlendAndIndicesStride / 4) - 3 - 1; // -3 to remove xyz, -1 to remove indices which come after
				for(size_t i = 0; i < blendCount; ++i)
				{
					*vtBlendWeightBuf = posData[3 + i]; vtBlendWeightBuf++;
				}
				vtBlendWeightBuf += 4 - blendCount; //each item is an array of 4 floats

				// Get blend indices
				// TODO SKIN Check the format we have to send this data as.
				if ( ContainsFlag(meshFVF, D3DFVF_LASTBETA_UBYTE4) )
				{
					*vtBlendIndicesBuf = ((DWORD*)vbptr)[3 + blendCount]; vtBlendIndicesBuf++;
				}
			}

			vbptr += positionBlendAndIndicesStride;
		}
		else
		{
			VCN_ASSERT_FAIL( VCNTXT("Mesh FVF not supported (no vertex position) [FVF = %d, stride = %d]"), meshFVF, stride );
		}

		// Read normal
		if ( ContainsFlag(meshFVF, D3DFVF_NORMAL) )
		{
			D3DXVECTOR3* normal = (D3DXVECTOR3*)(vbptr);
			*vtNormalBuf = normal->x; vtNormalBuf++;
			*vtNormalBuf = normal->y; vtNormalBuf++;
			*vtNormalBuf = normal->z; vtNormalBuf++;

			// Set default diffuse color
			std::fill(vtNormalBuf, vtNormalBuf+3, 1.0f); vtNormalBuf += 3;

			vbptr += normalStride;
		}
		else
		{
			VCN_ASSERT_FAIL( VCNTXT("Mesh FVF not supported (no normals) [FVF = %d, stride = %d]"), meshFVF, stride );
		}

		if ( ContainsFlag(meshFVF, D3DFVF_DIFFUSE) ) vbptr += diffuseStride;

		// Read texcoords
		// the check with D3DFVF_TEX0 is pretty useless as it's always true... the flag value is 0...
		if ( ContainsFlag(meshFVF, D3DFVF_TEX0) || ContainsFlag(meshFVF, D3DFVF_TEX1) )
		{
			float* texCoords = (float*)(vbptr);
			*vtTextureBuf = texCoords[0]; vtTextureBuf++;
			*vtTextureBuf = texCoords[1]; vtTextureBuf++;

			vbptr += textureStride;
		}
		else
		{
			VCN_ASSERT_FAIL( VCNTXT("Mesh FVF not supported (no texture coordinates) [FVF = %d, stride = %d]"), meshFVF, stride );
		}

		vblineptr += stride;
	}
	systemMesh->UnlockVertexBuffer();

	VCND3D9* renderer = VCNRenderCore::GetInstance()->Cast<VCND3D9>();

	// Generate cache resources that will be bind to Vicuna's meshes
	VCNResID positionCache = renderer->CreateCache(VT_POSITION, &vtPositionBuffer[0], vertexCount * kCacheStrides[VT_POSITION]);
	VCNResID lightingCache = renderer->CreateCache(VT_LIGHTING, &vtNormalBuffer[0], vertexCount * kCacheStrides[VT_LIGHTING]);
	VCNResID textureCache = renderer->CreateCache(VT_DIFFUSE_TEX_COORDS, &vtTextureBuffer[0], vertexCount * kCacheStrides[VT_DIFFUSE_TEX_COORDS]);

	VCNResID blendWeightCache = renderer->CreateCache(VT_BLENDWEIGHTS, &vtBlendWeights[0], vertexCount * kCacheStrides[VT_BLENDWEIGHTS]);
	VCNResID blendIndiceCache = renderer->CreateCache(VT_BLENDINDICES, &vtBlendIndices[0], vertexCount * kCacheStrides[VT_BLENDINDICES]);

	// Get model faces
	//
	VCNUShort* ibptr = 0;
	std::vector<VCNUShort> indices( systemMesh->GetNumFaces() * 3 );
	systemMesh->LockIndexBuffer(D3DLOCK_READONLY, (LPVOID*)&ibptr);
	for(VCNUInt i = 0; i < systemMesh->GetNumFaces(); i++)
	{
		indices[(i * 3) + 0] = *(ibptr++);
		indices[(i * 3) + 1] = *(ibptr++);
		indices[(i * 3) + 2] = *(ibptr++);
	}
	systemMesh->UnlockIndexBuffer();

	// Load materials
	//
	std::vector<VCNResID> materialIDS;
	D3DXMATERIAL* d3dxMaterials = meshContainer->pMaterials;
	for (DWORD i = 0; i < meshContainer->NumMaterials; ++i)
	{
		VCNResID materialID = kInvalidResID;

		// Create the texture if it exists - it may not
		if ( d3dxMaterials[i].pTextureFilename )
		{
			VCNResID textureID = kInvalidResID;

			VCNString texturePath = VCNTXT("Textures/");
			texturePath += VCN_A2W(d3dxMaterials[i].pTextureFilename);

			// Check if the texture is already loaded
			VCND3D9Texture* resTexture = VCNResourceCore::GetInstance()->GetResource<VCND3D9Texture>(texturePath);
			if ( !resTexture )
			{
				textureID = VCNMaterialCore::GetInstance()->CreateTexture(texturePath);
				VCN_ASSERT_MSG( textureID != kInvalidResID, VCNTXT("Can't load texture %s"), texturePath.c_str() );
			}
			else
			{
				textureID = resTexture->GetResourceID();
			}

			VCNMaterial* material = new VCNMaterial();
			const VCNString materialName = StringBuilder() << name << VCNTXT("_material_") << i;
			material->SetName( materialName );
			VCNColor ambient = VCNColor((const VCNFloat*)&d3dxMaterials[i].MatD3D.Ambient);
			ambient.a = 1.0f;
			ambient += VCNColor(0.5f, 0.5f, 0.5f, 0);

			material->SetAmbientColor( ambient );
			material->SetDiffuseColor( VCNColor((const VCNFloat*)&d3dxMaterials[i].MatD3D.Diffuse) );
			material->SetSpecularColor( VCNColor((const VCNFloat*)&d3dxMaterials[i].MatD3D.Specular) );
			material->SetSpecularPower( d3dxMaterials[i].MatD3D.Power );

			VCNEffectParamSet& params = material->GetEffectParamSet();
			params.SetEffectID( eidSkinned );
			params.AddResource( VCNTXT("DiffuseTexture"), textureID );

			// Add material as a resource.
			materialID = VCNResourceCore::GetInstance()->AddResource( material->GetName(), material );
		}

		materialIDS.push_back( materialID );
	}

	// Get the model attribute table with which we will instantiate has many mesh.
	//
	DWORD attribTableSize;
	std::vector<D3DXATTRIBUTERANGE> attribTable;
	HRESULT hr = systemMesh->GetAttributeTable( 0, &attribTableSize );
	if ( FAILED(hr) )
		return 0;
	attribTable.resize( attribTableSize );
	hr = systemMesh->GetAttributeTable( &attribTable[0], &attribTableSize );
	if ( FAILED(hr) )
		return 0;

	// Set the root node
	VCNNode* rootNode = attribTableSize > 1 ?  VCNNodeCore::GetInstance()->CreateNode<VCNNode>() : 
		VCNNodeCore::GetInstance()->CreateNode<VCNRenderNode>();

	rootNode->SetTag( StringBuilder() << name << VCNTXT("_Root") );

	// For each attribute, we get the material texture
	for (DWORD i = 0; i < attribTableSize; ++i)
	{
		VCNRenderNode* partNode = attribTableSize == 1 ? 
			safe_pointer_cast<VCNRenderNode*>( rootNode ) : 
		VCNNodeCore::GetInstance()->CreateNode<VCNRenderNode>();

		const VCNString partNodeName = StringBuilder() << name << VCNTXT("_Part_") << i;
		partNode->SetTag( partNodeName );

		VCNMesh* partMesh = new VCNMesh();
		partMesh->SetCacheID(VT_POSITION, positionCache); //SKIN do this for blend weights and blend indices
		partMesh->SetCacheID(VT_LIGHTING, lightingCache);
		partMesh->SetCacheID(VT_DIFFUSE_TEX_COORDS, textureCache);
		partMesh->SetCacheID(VT_BLENDWEIGHTS, blendWeightCache);
		partMesh->SetCacheID(VT_BLENDINDICES, blendIndiceCache);
		partMesh->SetPrimitiveType(PT_TRIANGLELIST);

		partMesh->SetBoneInfluenceCount( meshContainer->m_dwMaxNumFaceInfls );
		size_t numBones = meshContainer->pSkinInfo == nullptr ? 0 : meshContainer->pSkinInfo->GetNumBones();
		if (numBones > 0)
		{
			auto offsets = std::vector<Matrix4>(numBones);
			std::transform( std::begin(meshContainer->m_amxBoneOffsets), std::end(meshContainer->m_amxBoneOffsets), std::begin(offsets), [](const D3DXMATRIX& mat)
			{
				return Matrix4( (VCNFloat*)mat.m );
			});

			partMesh->SetBoneOffsets( std::move(offsets) );

			LPD3DXBONECOMBINATION boneCombination = reinterpret_cast<LPD3DXBONECOMBINATION>( 
				meshContainer->m_pBufBoneCombos->GetBufferPointer() );

			size_t numPaletteEntries = meshContainer->m_dwNumPaletteEntries;

			std::vector<size_t> matriceIndexes;

			for(size_t paletteIndex = 0; paletteIndex < numPaletteEntries; ++paletteIndex)
			{
				size_t matIndex = boneCombination[i].BoneId[paletteIndex];
				if ( matIndex == std::numeric_limits<size_t>::max())
					continue;

				matriceIndexes.push_back(matIndex);
			}

			partMesh->SetMatrixPaletteIndexes(matriceIndexes);
		}

		const DWORD partFaceCount = attribTable[i].FaceCount;
		const void* partFaceBufferStart = &indices[attribTable[i].FaceStart * 3];
		const VCNResID indexCacheID = renderer->CreateCache(VT_INDEX, partFaceBufferStart, partFaceCount * 3 * kCacheStrides[VT_INDEX]);
		partMesh->SetFaceCount( attribTable[i].FaceCount );
		partMesh->SetFaceCache( indexCacheID );

		// Compute bounding sphere
		float radius;
		D3DXVECTOR3 center;
		D3DXComputeBoundingSphere( (D3DXVECTOR3*)(&vtPositionBuffer[0] + attribTable[i].VertexStart * 3), 
			attribTable[i].VertexCount, stride, &center, &radius );
		VCNSphere modelBoundSphere( radius, V2V<Vector3>(center) );
		partMesh->SetBoundingSphere( modelBoundSphere );

		// Add mesh resource
		const VCNString partMeshName = StringBuilder() << name << VCNTXT("_part_") << i;
		const VCNResID partMeshID = VCNResourceCore::GetInstance()->AddResource( partMeshName, partMesh );

		// Set model part node attributes
		partNode->SetMeshID( partMeshID );
		if (animController && numBones > 0)
		{
			partNode->AddComponent( new VCND3DAnimator(partMeshID, animController, frameRoot, meshContainer->m_apmxBonePointers) );
		}

		size_t index = attribTable[i].AttribId;
		index = index >= materialIDS.size() ? materialIDS.size() - 1 : index;

		partNode->SetMaterialID( materialIDS[index] );

		// Add children to root
		if ( attribTableSize > 1 )
		{
			rootNode->AttachChild( partNode->GetNodeID() );
		}
	}

	return rootNode;
}
Example #15
0
void Scene::LoadFromXFile(string file, IDirect3DDevice9 *device)
{
    assert(device);

    ID3DXBuffer *material = nullptr;
    DWORD num_material = 0;
    ID3DXMesh *mesh = nullptr;

    HRESULT res = D3DXLoadMeshFromX(file.c_str(),     // pFilename
                                    D3DXMESH_DYNAMIC, // Options
                                    device,           // pD3DDevice
                                    nullptr,          // ppAdjacency
                                    &material,        // ppMaterials
                                    nullptr,          // ppEffectInstances
                                    &num_material,    // pNumMaterials
                                    &mesh);           // ppMesh
    if (FAILED(res))
    {
        Logger::GtLogError("load mesh from X file failed:%s", file.c_str());
        return;
    }
    assert(num_material == 1);
    D3DXMATERIAL *mat = static_cast<D3DXMATERIAL *>(material->GetBufferPointer());
    material_.ambient.r = mat->MatD3D.Ambient.r;
    material_.ambient.g = mat->MatD3D.Ambient.g;
    material_.ambient.b = mat->MatD3D.Ambient.b;
    material_.ambient.a = mat->MatD3D.Ambient.a;

    material_.diffuse.r = mat->MatD3D.Diffuse.r;
    material_.diffuse.g = mat->MatD3D.Diffuse.g;    
    material_.diffuse.b = mat->MatD3D.Diffuse.b;
    material_.diffuse.a = mat->MatD3D.Diffuse.a;

    material_.specular.r = mat->MatD3D.Specular.r;
    material_.specular.g = mat->MatD3D.Specular.g;
    material_.specular.b = mat->MatD3D.Specular.b;
    material_.specular.a = mat->MatD3D.Specular.a;

    material_.emissive.r = mat->MatD3D.Emissive.r;
    material_.emissive.g = mat->MatD3D.Emissive.g;
    material_.emissive.b = mat->MatD3D.Emissive.b;
    material_.emissive.a = mat->MatD3D.Emissive.a;

    material_.power = mat->MatD3D.Power;

    bool ret = texture_.Load(mat->pTextureFilename, device);
    assert(ret);
    material->Release();
    

    DWORD num_vertex = mesh->GetNumVertices();
    IDirect3DVertexBuffer9 *vertex_buffer = nullptr;
    res = mesh->GetVertexBuffer(&vertex_buffer);
    assert(SUCCEEDED(res));
    uint8 *vertex_data = nullptr;
    res = vertex_buffer->Lock(0, 0, reinterpret_cast<void **>(&vertex_data), D3DLOCK_READONLY);
    assert(SUCCEEDED(res));

    D3DVERTEXELEMENT9 vertex_elements[MAX_FVF_DECL_SIZE] = {0};
    res = mesh->GetDeclaration(vertex_elements);
    assert(SUCCEEDED(res));
    int offset_pos = 0;
    int offset_nor = 0;
    int offset_tex = 0;
    int vertex_size = mesh->GetNumBytesPerVertex();
    for (int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
    {
        if (vertex_elements[i].Type == D3DDECLTYPE_UNUSED)
            break;
        if (vertex_elements[i].Usage == D3DDECLUSAGE_POSITION)
        {
            offset_pos = vertex_elements[i].Offset;
        }
        if (vertex_elements[i].Usage == D3DDECLUSAGE_NORMAL)
        {
            offset_nor =  vertex_elements[i].Offset;
        }
        if (vertex_elements[i].Usage == D3DDECLUSAGE_TEXCOORD)
        {
            offset_tex = vertex_elements[i].Offset;
        }
    }

    Primitive  verteies(num_vertex, nullptr, nullptr);
    for (int i = 0; i < num_vertex; ++i)
    {
        verteies.positions[i] = *reinterpret_cast<Vector3 *>(vertex_data + vertex_size * i + offset_pos);
        verteies.positions[i].Display();
        verteies.normals[i] = *reinterpret_cast<Vector3 *>(vertex_data + vertex_size * i + offset_nor);
        verteies.normals[i].Display();
        verteies.uvs[i] = *reinterpret_cast<Vector2 *>(vertex_data + vertex_size * i + offset_tex);
        verteies.uvs[i].Display();
    }
    primitive_ = verteies;

    vertex_buffer->Unlock();
    vertex_buffer->Release();
}
Example #16
0
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    WNDCLASS wc;

    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc = (WNDPROC) MainWindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "xtocmod";
    if (RegisterClass(&wc) == 0)
    {
	MessageBox(NULL,
                   "Failed to register the window class.", "Fatal Error",
                   MB_OK | MB_ICONERROR);
	return NULL;
    }

    DWORD windowStyle = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
                         WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
    g_mainWindow = CreateWindow("xtocmod",
                                "xtocmod",
                                windowStyle,
                                CW_USEDEFAULT,
                                CW_USEDEFAULT,
                                300, 300,
                                NULL,
                                NULL,
                                hInstance,
                                NULL);
    if (g_mainWindow == NULL)
    {
        MessageBox(NULL,
                   "Error creating application window.", "Fatal Error",
                   MB_OK | MB_ICONERROR);
    }

    //ShowWindow(g_mainWindow, SW_SHOW);
    SetForegroundWindow(g_mainWindow);
    SetFocus(g_mainWindow);

    // Initialize D3D
    g_d3d = Direct3DCreate9(D3D_SDK_VERSION);
    if (g_d3d == NULL)
    {
        ShowD3DErrorMessage("Initializing D3D", 0);
        return 1;
    }

    D3DPRESENT_PARAMETERS presentParams;
    ZeroMemory(&presentParams, sizeof(presentParams));
    presentParams.Windowed = TRUE;
    presentParams.SwapEffect = D3DSWAPEFFECT_COPY;
#if 0
    presentParams.BackBufferWidth = 300;
    presentParams.BackBufferHeight = 300;
    presentParams.BackBufferCount = 1;
    presentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    presentParams.Windowed = TRUE;
#endif
    
    HRESULT hr = g_d3d->CreateDevice(D3DADAPTER_DEFAULT,
                                     D3DDEVTYPE_HAL,
                                     g_mainWindow,
                                     D3DCREATE_HARDWARE_VERTEXPROCESSING,
                                     &presentParams,
                                     &g_d3dDev);
    if (FAILED(hr))
    {
        ShowD3DErrorMessage("Creating D3D device", hr);
        //return 1;
    }

    string inputFilename(lpCmdLine);
    string outputFilename(inputFilename, 0, inputFilename.rfind('.'));
    outputFilename += ".cmod";

    ID3DXMesh* mesh = NULL;
    ID3DXBuffer* adjacency = NULL;
    ID3DXBuffer* materialBuf = NULL;
    ID3DXBuffer* effects = NULL;
    DWORD numMaterials;
    
    hr = D3DXLoadMeshFromX(inputFilename.c_str(),
                           0,
                           g_d3dDev,
                           &adjacency,
                           &materialBuf,
                           &effects,
                           &numMaterials,
                           &mesh);
    if (FAILED(hr))
    {
        ShowD3DErrorMessage("Loading mesh from X file", hr);
        return 1;
    }


    DWORD numVertices = mesh->GetNumVertices();
    DWORD numFaces = mesh->GetNumFaces();

    cout << "vertices: " << numVertices << '\n';
    cout << "faces: " << numFaces << '\n';

    cout << "adjacency buffer size: " << adjacency->GetBufferSize() << '\n';

    ofstream meshfile(outputFilename.c_str());

    // Output the header
    meshfile << "#celmodel__ascii\n\n";

    cout << "numMaterials=" << numMaterials << '\n';
    D3DXMATERIAL* materials = reinterpret_cast<D3DXMATERIAL*>(materialBuf->GetBufferPointer());
    for (DWORD mat = 0; mat < numMaterials; mat++)
    {
        meshfile << "material\n";
        meshfile << "diffuse " << materials[mat].MatD3D.Diffuse << '\n';
        //meshfile << "emissive " << materials[mat].MatD3D.Emissive << '\n';
        meshfile << "specular " << materials[mat].MatD3D.Specular << '\n';
        meshfile << "specpower " << materials[mat].MatD3D.Power << '\n';
        meshfile << "opacity " << materials[mat].MatD3D.Diffuse.a << '\n';
        meshfile << "end_material\n\n";
    }

    // Vertex format
    D3DVERTEXELEMENT9 declElements[MAX_FVF_DECL_SIZE];
    hr = mesh->GetDeclaration(declElements);
    if (FAILED(hr))
    {
        ShowD3DErrorMessage("Checking vertex declaration", hr);
        return 1;
    }

    DWORD stride = D3DXGetDeclVertexSize(declElements, 0);

    VertexAttribute vertexMap[VertexAttribute::MaxAttribute];
    CreateVertexAttributeMap(declElements, vertexMap);

    meshfile << "mesh\n\n";

    DumpVertexDescription(vertexMap, meshfile);

    ID3DXMesh* optMesh = NULL;
    ID3DXBuffer* vertexRemap = NULL;
    DWORD* faceRemap = new DWORD[numFaces];
    DWORD* optAdjacency = new DWORD[numFaces * 3];
    hr = mesh->Optimize(D3DXMESHOPT_COMPACT | D3DXMESHOPT_STRIPREORDER,
                        //D3DXMESHOPT_VERTEXCACHE |
                        reinterpret_cast<DWORD*>(adjacency->GetBufferPointer()),
                        optAdjacency,
                        faceRemap,
                        &vertexRemap,
                        &optMesh);
    if (FAILED(hr))
    {
        ShowD3DErrorMessage("Optimize failed: ", hr);
        return 1;
    }
    
    // Attribute table
    DWORD attribTableSize = 0;
    hr = optMesh->GetAttributeTable(NULL, &attribTableSize);
    if (FAILED(hr))
    {
        ShowD3DErrorMessage("Querying attribute table size", hr);
        return 1;
    }

    D3DXATTRIBUTERANGE* attribTable = NULL;
    if (attribTableSize > 0)
    {
        attribTable = new D3DXATTRIBUTERANGE[attribTableSize];
        hr = optMesh->GetAttributeTable(attribTable, &attribTableSize);
        if (FAILED(hr))
        {
            ShowD3DErrorMessage("Getting attribute table", hr);
            return 1;
        }
    }

    cout << "Attribute table size: " << attribTableSize << '\n';
    if (attribTableSize == 1)
    {
        cout << "Attribute id: " << attribTable[0].AttribId << '\n';
    }

    if (!DumpMeshVertices(optMesh, vertexMap, stride, meshfile))
        return 1;
    
    // output the indices
    for (DWORD attr = 0; attr < attribTableSize; attr++)
    {
        StripifyMeshSubset(optMesh, attr, meshfile);
    }
    meshfile << "\nend_mesh\n";

#if 0
    IDirect3DIndexBuffer9* indices = NULL;
    hr = mesh->GetIndexBuffer(&indices);
#endif

#if 0
    // No message loop required for this app
    MSG msg;
    GetMessage(&msg, NULL, 0u, 0u);
    while (msg.message != WM_QUIT)
    {
        GetMessage(&msg, NULL, 0u, 0u);
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
#endif

    return 0;
}
void LODManager::Render(IDirect3DDevice9 *D3DDevice) {
  const char *meshpath =
    (lod == GRID_FARNEAR ? "landscape\\lod\\farnear\\" :
    (lod == GRID_FARFAR  ? "landscape\\lod\\farfar\\" :
			   "landscape\\lod\\farinf\\"));
  const char *textpath =
    (lod == GRID_FARNEAR ? "landscapelod\\generated\\farnear\\" :
    (lod == GRID_FARFAR  ? "landscapelod\\generated\\farfar\\" :
			   "landscapelod\\generated\\farinf\\"));

  int nativeminx = (GRID_SIZE * 32) + (Constants.Coordinates.x - GridDistantCount.Get());
  int nativeminy = (GRID_SIZE * 32) + (Constants.Coordinates.y - GridDistantCount.Get());
  int nativemaxx = (GRID_SIZE * 32) + (Constants.Coordinates.x + GridDistantCount.Get());
  int nativemaxy = (GRID_SIZE * 32) + (Constants.Coordinates.y + GridDistantCount.Get());

  /* y-axis has flipped rounding */
  nativeminx = (nativeminx / 32) - GRID_SIZE;
  nativeminy = (nativeminy / 32) - GRID_SIZE + 0;
  nativemaxx = (nativemaxx / 32) - GRID_SIZE;
  nativemaxy = (nativemaxy / 32) - GRID_SIZE + 0;

  int gridx = Constants.Coordinates.x / 32;
  int gridy = Constants.Coordinates.y / 32;
  for (int x = (gridx - extend); x <= (gridx + extend); x++)
  for (int y = (gridy - extend); y <= (gridy + extend); y++) {
    /* TODO: try radius, seems it's not a box */
    /* leave out Oblivion's native tiles */
    if ((x >= nativeminx) && (x <= nativemaxx) &&
	(y >= nativeminy) && (y <= nativemaxy))
      continue;
    /* leave out other LOD's inner tiles */
    if ((abs(gridx - x) <= inner) &&
	(abs(gridy - y) <= inner))
      continue;

    /* where are we? */
    const float TileOffset[4] = {x * TILE_DIM, y * TILE_DIM, 0, 0};

    /* filter outside-array coordinates */
    if (((GRID_OFFSET + y) >= 0) && ((GRID_OFFSET + y) < GRID_SIZE) &&
	((GRID_OFFSET + x) >= 0) && ((GRID_OFFSET + x) < GRID_SIZE)) {

      /* never seen, never attempted */
      if (MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) {
	/* TODO: 32 means 32x32 cells, in theory that can be different as well */
	char buf[256]; sprintf(buf, "%02d.%02d.%02d.32", WorldSpace, x * 32, y * 32);
	char pth[256]; strcpy(pth, meshpath); strcat(pth, buf); strcat(pth, ".x");

	/* no textures without mesh, but we can render texture-free */
	if ((MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] =
	    MeshManager::GetSingleton()->LoadPrivateMesh(pth, MR_REGULAR)) != -1) {

	  if (ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) {
	    strcpy(pth, textpath); strcat(pth, buf); strcat(pth, ".dds");
	    ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] =
	      TextureManager::GetSingleton()->LoadPrivateTexture(pth, TR_PLANAR);
	  }

	  if (NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) {
	    strcpy(pth, textpath); strcat(pth, buf); strcat(pth, "_fn.dds");
	    NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] =
	      TextureManager::GetSingleton()->LoadPrivateTexture(pth, TR_PLANAR);
	  }

	  /* put the addresses */
	  ManagedMeshRecord    *mesh = Meshes [lod][GRID_OFFSET + y][GRID_OFFSET + x] =    MeshManager::GetSingleton()->GetMesh   (MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]);
	  ManagedTextureRecord *colr = Colors [lod][GRID_OFFSET + y][GRID_OFFSET + x] = TextureManager::GetSingleton()->GetTexture(ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]);
	  ManagedTextureRecord *norm = Normals[lod][GRID_OFFSET + y][GRID_OFFSET + x] = TextureManager::GetSingleton()->GetTexture(NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]);

	  /* failure to load all resources */
	  if (!mesh || !colr || !norm) {
	    if (mesh) mesh->Release();
	    if (colr) colr->Release();
	    if (norm) norm->Release();

	    MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1;
	    ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1;
	    NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1;

	    continue;
	  }

#if	defined(OBGE_GAMMACORRECTION)
	  /* remember DeGamma for this kind of texture */
	  static const bool PotDeGamma = true;
	  colr->GetTexture()->SetPrivateData(GammaGUID, &PotDeGamma, sizeof(PotDeGamma), 0);
#endif
	}
      }

      /* get the addresses */
      ManagedMeshRecord    *mesh = Meshes [lod][GRID_OFFSET + y][GRID_OFFSET + x];
      ManagedTextureRecord *colr = Colors [lod][GRID_OFFSET + y][GRID_OFFSET + x];
      ManagedTextureRecord *norm = Normals[lod][GRID_OFFSET + y][GRID_OFFSET + x];

      ID3DXMesh *m;
      if (mesh && (m = (ID3DXMesh *)mesh->GetMesh())) {
#if 0
	DWORD FVF  = m->GetFVF();
	DWORD size = m->GetNumBytesPerVertex();
	DWORD numf = m->GetNumFaces();
	DWORD numv = m->GetNumVertices();

	IDirect3DIndexBuffer9 *pIB; m->GetIndexBuffer(&pIB);
	IDirect3DVertexBuffer9 *pVB; m->GetVertexBuffer(&pVB);

	D3DDevice->SetStreamSource(0, pVB, 0, size);
	D3DDevice->SetFVF(FVF);
	D3DDevice->SetTexture(0, colr->GetTexture());
	D3DDevice->SetTexture(1, norm->GetTexture());
	D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numv, 0, numf);
#endif

	D3DDevice->SetTexture(0, colr ? colr->GetTexture() : NULL);
	D3DDevice->SetTexture(1, norm ? norm->GetTexture() : NULL);

	D3DDevice->SetVertexShader(vShader[lod]);
	D3DDevice->SetPixelShader (pShader[lod]);
	D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1);

	m->DrawSubset(0);
      }
    }

    /* water-planes */
    D3DDevice->SetVertexShader(vShaderW);
    D3DDevice->SetPixelShader (pShaderW);
    D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1);

    D3DDevice->SetStreamSource(0, WaterVertex, 0, sizeof(WaterTile));
    D3DDevice->SetFVF(WATERTILEFORMAT);
    D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
  }

  const float TileOffset[4] = {0, 0, 0, 1};

  /* infini-plane */
  D3DDevice->SetVertexShader(vShaderW);
  D3DDevice->SetPixelShader (pShaderW);
  D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1);

  D3DDevice->SetStreamSource(0, InfiniteVertex, 0, sizeof(WaterTile));
  D3DDevice->SetFVF(WATERTILEFORMAT);
  D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
Example #18
0
void SphereCylDemo::genCylTexCoords(AXIS axis)
{
	// D3DXCreate* functions generate vertices with position 
	// and normal data.  But for texturing, we also need
	// tex-coords.  So clone the mesh to change the vertex
	// format to a format with tex-coords.

	D3DVERTEXELEMENT9 elements[64];
	UINT numElements = 0;
	VertexPNT::Decl->GetDeclaration(elements, &numElements);

	ID3DXMesh* temp = 0;
	HR(mCylinder->CloneMesh(D3DXMESH_SYSTEMMEM, 
		elements, gd3dDevice, &temp));

	ReleaseCOM(mCylinder);

	// Now generate texture coordinates for each vertex.
	VertexPNT* vertices = 0;
	HR(temp->LockVertexBuffer(0, (void**)&vertices));

	// We need to get the height of the cylinder we are projecting the
	// vertices onto.  That height depends on which axis the client has
	// specified that the cylinder lies on.  The height is determined by 
	// finding the height of the bounding cylinder on the specified axis.

	D3DXVECTOR3 maxPoint(-FLT_MAX, -FLT_MAX, -FLT_MAX);
	D3DXVECTOR3 minPoint(FLT_MAX, FLT_MAX, FLT_MAX);

	for(UINT i = 0; i < temp->GetNumVertices(); ++i)
	{
		D3DXVec3Maximize(&maxPoint, &maxPoint, &vertices[i].pos);
		D3DXVec3Minimize(&minPoint, &minPoint, &vertices[i].pos);
	}

	float a = 0.0f;
	float b = 0.0f;
	float h = 0.0f;
	switch( axis )
	{
	case X_AXIS:
		a = minPoint.x;
		b = maxPoint.x;
		h = b-a;
		break;
	case Y_AXIS:
		a = minPoint.y;
		b = maxPoint.y;
		h = b-a;
		break;
	case Z_AXIS:
		a = minPoint.z;
		b = maxPoint.z;
		h = b-a;
		break;
	}


	// Iterate over each vertex and compute its texture coordinate.

	for(UINT i = 0; i < temp->GetNumVertices(); ++i)
	{
		// Get the coordinates along the axes orthogonal to the
		// axis the cylinder is aligned with.

		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
		switch( axis )
		{
		case X_AXIS:
			x = vertices[i].pos.y;
			z = vertices[i].pos.z;
			y = vertices[i].pos.x;
			break;
		case Y_AXIS:
			x = vertices[i].pos.x;
			z = vertices[i].pos.z;
			y = vertices[i].pos.y;
			break;
		case Z_AXIS:
			x = vertices[i].pos.x;
			z = vertices[i].pos.y;
			y = vertices[i].pos.z;
			break;
		}

		// Convert to cylindrical coordinates.

		float theta = atan2f(z, x);
		float y2    = y - b; // Transform [a, b]-->[-h, 0]

		// Transform theta from [0, 2*pi] to [0, 1] range and
		// transform y2 from [-h, 0] to [0, 1].

		float u = theta / (2.0f*D3DX_PI);
		float v = y2 / -h; 

		// Save texture coordinates.

		vertices[i].tex0.x = u;
		vertices[i].tex0.y = v;
	}

	HR(temp->UnlockVertexBuffer());

	// Clone back to a hardware mesh.
	HR(temp->CloneMesh(D3DXMESH_MANAGED | D3DXMESH_WRITEONLY,
		elements, gd3dDevice, &mCylinder));

	ReleaseCOM(temp);
}