//--------------------------------------------------------------------------------------
HRESULT CLoaderXFile::Load( WCHAR* szFileName, FRAME_TRANSFORM_TYPE requestedBHT )
{
    HRESULT hr = E_FAIL;
    ID3DXBuffer *pMat = NULL;
    ID3DXMesh *pRawMesh = NULL;
    ID3DXMesh *pMesh = NULL;
    DWORD cMat;
    IDirect3DDevice9* pDev9 = NULL;
    DWORD* pAdjBuffer = NULL;

    // Create a d3d9 object
    IDirect3D9* pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );

    if( pD3D9 == NULL )
        return E_FAIL;

    D3DPRESENT_PARAMETERS pp;
    pp.BackBufferWidth = 320;
    pp.BackBufferHeight = 240;
    pp.BackBufferFormat = D3DFMT_X8R8G8B8;
    pp.BackBufferCount = 1;
    pp.MultiSampleType = D3DMULTISAMPLE_NONE;
    pp.MultiSampleQuality = 0;
    pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    pp.hDeviceWindow = GetShellWindow();
    pp.Windowed = true;
    pp.Flags = 0;
    pp.FullScreen_RefreshRateInHz = 0;
    pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
    pp.EnableAutoDepthStencil = false;

    hr = pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pp, &pDev9 );
    if(FAILED(hr))
        goto Error;

    if( szFileName )
    {
        hr = D3DXLoadMeshFromX( szFileName, 0, pDev9, NULL, &pMat, NULL, &cMat, &pRawMesh );
        if(FAILED(hr))
            goto Error;
    }

    D3DVERTEXELEMENT9 declTanBi[] = 
    {
        { 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 },
        { 0, 32, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,  0 },
        { 0, 44, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,  0 },
        D3DDECL_END()
    };
    D3DVERTEXELEMENT9* pdecl = declTanBi;

    // Make a clone with the desired vertex format.
    if( SUCCEEDED( pRawMesh->CloneMesh( D3DXMESH_32BIT | D3DXMESH_DYNAMIC, pdecl, pDev9, &m_pMesh ) ) )
    {
        // Optimize
        pAdjBuffer = new DWORD[ 3*m_pMesh->GetNumFaces() ];
        if( !pAdjBuffer )
        {
            hr = E_OUTOFMEMORY;
            goto Error;
        }
        m_pMesh->GenerateAdjacency( 0.001f, pAdjBuffer );
        m_pMesh->OptimizeInplace( D3DXMESHOPT_ATTRSORT,
                                    pAdjBuffer,
                                    NULL,
                                    NULL,
                                    NULL );

        // Attributes
        m_pMesh->GetAttributeTable( NULL, &m_dwNumAttr );
        if( m_dwNumAttr > 0 )
        {
            m_pAttr = new D3DXATTRIBUTERANGE[m_dwNumAttr];
            m_pMesh->GetAttributeTable( m_pAttr, &m_dwNumAttr );
        }

        // Materials
        m_dwNumMaterials = cMat;
        if( m_dwNumMaterials > 0 )
        {
            D3DXMATERIAL* pMaterialBuffer = (D3DXMATERIAL*)pMat->GetBufferPointer();
            m_pMats = new D3DXMATERIAL[ m_dwNumMaterials ];
            if( !m_pMats )
            {
                hr = E_OUTOFMEMORY;
                goto Error;
            }

            for( DWORD m=0; m<m_dwNumMaterials; m++ )
            {
                CopyMemory( &m_pMats[m], &pMaterialBuffer[m], sizeof(D3DXMATERIAL) );
            }
        }

        // Create the intermediate mesh
        hr = CreateIntermediateMesh( declTanBi, 6 );
        if(FAILED(hr))
            goto Error;
    }

    hr = S_OK;
Error:
    SAFE_RELEASE( pMat );
    SAFE_RELEASE( pRawMesh );
    SAFE_RELEASE( pMesh );
    SAFE_RELEASE( pDev9 );
    SAFE_RELEASE( pD3D9 );
    SAFE_DELETE_ARRAY( pAdjBuffer );

    return hr;
}
Beispiel #2
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
}
/** 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();
}
Beispiel #4
0
// This functions creates a sphere of "radius" and vertex color "color"
bool CreateSphere(float radius, int color, ID3DXMesh **mesh)
{
    assert(g3D->mDevice != NULL);
    assert(mesh != NULL);

    // This is the number of divisions the sphere will have vertically and
    // horizontally
    const unsigned int kSlices = 16; // Vertical divisions
    const unsigned int kStacks = 16; // Horizontal divisions

    ID3DXMesh *temp = NULL; // Temp D3D mesh object

    // Create the sphere
    // By parameter:
    // g3D->mDevice -- Pointer to the Direct3D device to be associated with the sphere
    // radius -- Radius of the sphere
    // kSlices -- Number of vertical divisions in the sphere
    // kStacks -- Number of horizontal divisions in the sphere
    // &temp -- A pointer to a ID3DXMesh*, it will get filled with the
    //			the created mesh
    // NULL --  Optional pointer to a ID3DXBuffer, if a valid pointer was passed
    //			it would be filled with the adjacency information for each face in
    //			the mesh.  By passing NULL, we say we don't want this information
    if(D3DXCreateSphere(g3D->mDevice, radius, kSlices, kStacks, &temp, NULL) != D3D_OK)
        return false;

    // Next we clone the mesh.  This does two things.  First, it allows us to
    // specify the vertex format we want on the cloned mesh.  Second, it copies the
    // current mesh data into the ID3DXMesh we passed to this function.
    // By parameter:
    // D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED -- Flags specifying how we want the mesh to be
    //												cloned.  This particular flag combo says
    //												"Have the vertex buffer and index buffer
    //												associated with this mesh be in pooled memory
    //												that DirectX manages for us."
    // SVertexType -- Flexible vertex format that we want the cloned mesh to be converted to
    // g3D->mDevice -- IDirect3DDevice9 to associate this mesh with
    // mesh -- A pointer to a ID3DXMesh* that will get filled with the cloned mesh
    if(temp->CloneMeshFVF(D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED, SVertexType,
                          g3D->mDevice, mesh) != D3D_OK)
    {
        return false;
    }

    // Okay so up to this point we've created a stock D3D sphere, then converted
    // it a sphere with the FVF that we want.  Now were going to
    // loop through each vertex and set it to the color that we want it to be

    SVertex *v;

    // Lock the vertex buffer
    if((*mesh)->LockVertexBuffer(0, (void**)&v) != D3D_OK)
    {
        (*mesh)->Release();
        return false;
    }

    // Loop through all the verts in the mesh, setting each one's
    // color to the color passed into the function
    for(unsigned int i = 0; i < (*mesh)->GetNumVertices(); ++i)
        v[i].color = color;

    // Don't be stingy, unlock the vertex buffer so others can use it
    (*mesh)->UnlockVertexBuffer();

    temp->Release(); // Last but not least, free up the temporary mesh
    return true;
}
Beispiel #5
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.
}
Beispiel #6
0
void LoadXFile(const std::string & filename, ID3DXMesh** meshOut, std::vector<Mtrl> & mtrls, std::vector<IDirect3DTexture9*> & texs)
{
	ID3DXMesh* meshSys				= 0;
	ID3DXBuffer * adjBuffer			= 0;
	ID3DXBuffer * mtrlBuffer		= 0;
	DWORD numMtrls					= 0;

    //step 1. Load the x file into system memory
    HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM, gd3dDevice, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &meshSys));

    //step 2. look into MAX_FVF_DECL_SIZE
    D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
    HR(meshSys->GetDeclaration(elems));

    bool hasNormals = false;
	D3DVERTEXELEMENT9 term = D3DDECL_END();
    for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
    {
        //did we reach end?
        if(elems[i].Stream == 0xff)
            break;

        if(elems[i].Type == D3DDECLTYPE_FLOAT3 && elems[i].Usage == D3DDECLUSAGE_NORMAL && elems[i].UsageIndex == 0)
        {
            hasNormals = true;
            break;
        }
    }

    //step 3.
    D3DVERTEXELEMENT9 elements[64];
    UINT numElements = 0;
    VertexPNT::Decl->GetDeclaration(elements, &numElements);
   
    ID3DXMesh * temp = 0;
    //HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM, elements, gd3dDevice, &temp));
	 HR(meshSys->CloneMesh(D3DXMESH_32BIT, elements, gd3dDevice, &temp));
	ReleaseCOM(meshSys);
	meshSys = temp;

    //step 4
    if( hasNormals == false )
        HR(D3DXComputeNormals(meshSys, 0));

    //step 5
    HR(meshSys->Optimize(D3DXMESH_MANAGED | D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT
        | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut));

    ReleaseCOM(meshSys); //Done w/ system mesh
    ReleaseCOM(adjBuffer); //done with buffer

    //step 6: get the materials and load the textures
    if(mtrlBuffer != 0 && numMtrls != 0)
    {
		D3DXMATERIAL *d3dxMtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
		
		for(DWORD i = 0; i < numMtrls; ++i)
		{
			//save the ith material.  MatD3D ambient
			//doesnt have a default value, so I'm setting
			//it to be the same as the diffuse
			Mtrl m;
			m.ambient = d3dxMtrls[i].MatD3D.Diffuse;
			m.diffuse = d3dxMtrls[i].MatD3D.Diffuse;
			m.spec = d3dxMtrls[i].MatD3D.Specular;
			m.specPower = d3dxMtrls[i].MatD3D.Power;
			mtrls.push_back(m);

			//check if the ith material has an associative texture
			if(d3dxMtrls[i].pTextureFilename != 0)
			{
				//yes, load the texture for the ith subset
				IDirect3DTexture9* tex = 0;
				char *texFN = d3dxMtrls[i].pTextureFilename;
				HR(D3DXCreateTextureFromFile(gd3dDevice, texFN, &tex));

				//save the loaded texure
				texs.push_back(tex);
			}
			else
			{
				//no texture
				texs.push_back( 0 );
			}
		}
	}

	ReleaseCOM(mtrlBuffer); // done with the buffer
}
Beispiel #7
0
//--------------------------------------------------------------------------------------
HRESULT CMeshLoader::Create( IDirect3DDevice9* pd3dDevice, const WCHAR* strFilename )
{
    HRESULT hr;
    WCHAR str[ MAX_PATH ] = {0};

    // Start clean
    Destroy();

    // Store the device pointer
    m_pd3dDevice = pd3dDevice;

    // Load the vertex buffer, index buffer, and subset information from a file. In this case, 
    // an .obj file was chosen for simplicity, but it's meant to illustrate that ID3DXMesh objects
    // can be filled from any mesh file format once the necessary data is extracted from file.
    
    //V_RETURN( LoadGeometryFromOBJ( strFilename ) );
    V_RETURN( LoadGeometryFromOBJ_Fast( strFilename ) );

    // Set the current directory based on where the mesh was found
    WCHAR wstrOldDir[MAX_PATH] = {0};
    GetCurrentDirectory( MAX_PATH, wstrOldDir );
    SetCurrentDirectory( m_strMediaDir );

    // Load material textures
    for( int iMaterial = 0; iMaterial < m_Materials.GetSize(); iMaterial++ )
    {
        Material* pMaterial = m_Materials.GetAt( iMaterial );
        if( pMaterial->strTexture[0] )
        {
            // Avoid loading the same texture twice
            bool bFound = false;
            for( int x = 0; x < iMaterial; x++ )
            {
                Material* pCur = m_Materials.GetAt( x );
                if( 0 == wcscmp( pCur->strTexture, pMaterial->strTexture ) )
                {
                    bFound = true;
                    pMaterial->pTexture = pCur->pTexture;
                    break;
                }
            }

            // Not found, load the texture
            if( !bFound )
            {
                V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, pMaterial->strTexture ) );
                V_RETURN( D3DXCreateTextureFromFile( pd3dDevice, pMaterial->strTexture,
                                                     &( pMaterial->pTexture ) ) );
                int a = 0;
            }
        }
    }

    // Restore the original current directory
    SetCurrentDirectory( wstrOldDir );

    // Create the encapsulated mesh
    ID3DXMesh* pMesh = NULL;
    V_RETURN( D3DXCreateMesh( m_Indices.GetSize() / 3, m_Vertices.GetSize(),
                              D3DXMESH_MANAGED | D3DXMESH_32BIT, VERTEX_DECL,
                              pd3dDevice, &pMesh ) );

    // Copy the vertex data
    VERTEX* pVertex;
    V_RETURN( pMesh->LockVertexBuffer( 0, ( void** )&pVertex ) );
    memcpy( pVertex, m_Vertices.GetData(), m_Vertices.GetSize() * sizeof( VERTEX ) );
    pMesh->UnlockVertexBuffer();
    m_Vertices.RemoveAll();

    // Copy the index data
    DWORD* pIndex;
    V_RETURN( pMesh->LockIndexBuffer( 0, ( void** )&pIndex ) );
    memcpy( pIndex, m_Indices.GetData(), m_Indices.GetSize() * sizeof( DWORD ) );
    pMesh->UnlockIndexBuffer();
    m_Indices.RemoveAll();

    // Copy the attribute data
    DWORD* pSubset;
    V_RETURN( pMesh->LockAttributeBuffer( 0, &pSubset ) );
    memcpy( pSubset, m_Attributes.GetData(), m_Attributes.GetSize() * sizeof( DWORD ) );
    pMesh->UnlockAttributeBuffer();
    m_Attributes.RemoveAll();

    // Reorder the vertices according to subset and optimize the mesh for this graphics 
    // card's vertex cache. When rendering the mesh's triangle list the vertices will 
    // cache hit more often so it won't have to re-execute the vertex shader.
    DWORD* aAdjacency = new DWORD[pMesh->GetNumFaces() * 3];
    if( aAdjacency == NULL )
        return E_OUTOFMEMORY;

    V( pMesh->GenerateAdjacency( 1e-6f, aAdjacency ) );
    V( pMesh->OptimizeInplace( D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, aAdjacency, NULL, NULL, NULL ) );

    SAFE_DELETE_ARRAY( aAdjacency );
    m_pMesh = pMesh;

    return S_OK;
}
Beispiel #8
0
WaterDemo::WaterDemo(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
    : D3DApp(hInstance, winCaption, devType, requestedVP)
{
    if(!checkDeviceCaps())
    {
        MessageBox(0, "checkDeviceCaps() Failed", 0, 0);
        PostQuitMessage(0);
    }

    InitAllVertexDeclarations();

    mLight.dirW = D3DXVECTOR3(0.0f, -2.0f, -1.0f);
    D3DXVec3Normalize(&mLight.dirW, &mLight.dirW);
    mLight.ambient = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
    mLight.diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
    mLight.spec    = D3DXCOLOR(0.7f, 0.7f, 0.7f, 1.0f);

    mGfxStats = new GfxStats();
    mSky = new Sky("grassenvmap1024.dds", 10000.0f);

    D3DXMATRIX waterWorld;
    D3DXMatrixTranslation(&waterWorld, 0.0f, 2.0f, 0.0f);

    Mtrl waterMtrl;
    waterMtrl.ambient   = D3DXCOLOR(0.26f, 0.23f, 0.3f, 0.90f);
    waterMtrl.diffuse   = D3DXCOLOR(0.26f, 0.23f, 0.3f, 0.90f);
    waterMtrl.spec      = 1.0f*WHITE;
    waterMtrl.specPower = 64.0f;

    Water::InitInfo waterInitInfo;
    waterInitInfo.dirLight = mLight;
    waterInitInfo.mtrl     = waterMtrl;
    waterInitInfo.vertRows         = 128;
    waterInitInfo.vertCols         = 128;
    waterInitInfo.dx               = 1.0f;
    waterInitInfo.dz               = 1.0f;
    waterInitInfo.waveMapFilename0 = "wave0.dds";
    waterInitInfo.waveMapFilename1 = "wave1.dds";
    waterInitInfo.waveMapVelocity0 = D3DXVECTOR2(0.05f, 0.08f);
    waterInitInfo.waveMapVelocity1 = D3DXVECTOR2(-0.02f, 0.1f);
    waterInitInfo.texScale = 16.0f;
    waterInitInfo.toWorld = waterWorld;

    mWater = new Water(waterInitInfo);
    mWater->setEnvMap(mSky->getEnvMap());

    ID3DXMesh* tempMesh = 0;
    LoadXFile("BasicColumnScene.x", &tempMesh, mSceneMtrls, mSceneTextures);

    // Get the vertex declaration for the NMapVertex.
    D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
    UINT numElems = 0;
    HR(NMapVertex::Decl->GetDeclaration(elems, &numElems));

    // Clone the mesh to the NMapVertex format.
    ID3DXMesh* clonedTempMesh = 0;
    HR(tempMesh->CloneMesh(D3DXMESH_MANAGED, elems, gd3dDevice, &clonedTempMesh));

    // Now use D3DXComputeTangentFrameEx to build the TNB-basis for each vertex
    // in the mesh.

    HR(D3DXComputeTangentFrameEx(
           clonedTempMesh, // Input mesh
           D3DDECLUSAGE_TEXCOORD, 0, // Vertex element of input tex-coords.
           D3DDECLUSAGE_BINORMAL, 0, // Vertex element to output binormal.
           D3DDECLUSAGE_TANGENT, 0,  // Vertex element to output tangent.
           D3DDECLUSAGE_NORMAL, 0,   // Vertex element to output normal.
           0, // Options
           0, // Adjacency
           0.01f, 0.25f, 0.01f, // Thresholds for handling errors
           &mSceneMesh, // Output mesh
           0));         // Vertex Remapping

    // Done with temps.
    ReleaseCOM(tempMesh);
    ReleaseCOM(clonedTempMesh);

    D3DXMatrixIdentity(&mSceneWorld);
    D3DXMatrixIdentity(&mSceneWorldInv);

    HR(D3DXCreateTextureFromFile(gd3dDevice, "floor_nmap.bmp", &mSceneNormalMaps[0]));
    HR(D3DXCreateTextureFromFile(gd3dDevice, "bricks_nmap.bmp", &mSceneNormalMaps[1]));

    HR(D3DXCreateTextureFromFile(gd3dDevice, "whitetex.dds", &mWhiteTex));

    // Initialize camera.
    gCamera->pos().y = 7.0f;
    gCamera->pos().z = -30.0f;
    gCamera->setSpeed(10.0f);

    mGfxStats->addVertices(mSceneMesh->GetNumVertices());
    mGfxStats->addTriangles(mSceneMesh->GetNumFaces());

    mGfxStats->addVertices(mWater->getNumVertices());
    mGfxStats->addTriangles(mWater->getNumTriangles());

    mGfxStats->addVertices(mSky->getNumVertices());
    mGfxStats->addTriangles(mSky->getNumTriangles());


    buildFX();

    onResetDevice();
}
Beispiel #9
0
void PropsDemo::drawScene()
{
	// Clear the backbuffer and depth buffer.
	HR(gd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff888888, 1.0f, 0));

	HR(gd3dDevice->BeginScene());

	HR(mFX->SetValue(mhEyePosW, &gCamera->pos(), sizeof(D3DXVECTOR3)));
	HR(mFX->SetTechnique(mhTech));
	UINT numPasses = 0;
	HR(mFX->Begin(&numPasses, 0));
	HR(mFX->BeginPass(0));

	drawObject(mCastle, mCastleWorld);

	// Use alpha test to block non leaf pixels from being rendered in the
	// trees (i.e., use alpha mask).
	HR(gd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, true));
	HR(gd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL));
	HR(gd3dDevice->SetRenderState(D3DRS_ALPHAREF, 200));

	// Draw the trees: NUM_TREES/4 of each of the four types.
	for(int i = 0; i < NUM_TREES; ++i)
	{
		if( i < NUM_TREES/4 )
			drawObject(mTrees[0], mTreeWorlds[i]);
		else if( i < 2*NUM_TREES/4 )
			drawObject(mTrees[1], mTreeWorlds[i]);
		else if( i < 3*NUM_TREES/4 )
			drawObject(mTrees[2], mTreeWorlds[i]);
		else
			drawObject(mTrees[3], mTreeWorlds[i]);
	}

	HR(gd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false));

	HR(mFX->EndPass());
	HR(mFX->End());


	HR(mGrassFX->SetValue(mhGrassEyePosW, &gCamera->pos(), sizeof(D3DXVECTOR3)));
	HR(mGrassFX->SetMatrix(mhGrassViewProj, &(gCamera->viewProj())));
	HR(mGrassFX->SetFloat(mhGrassTime, mTime));
	HR(mGrassFX->Begin(&numPasses, 0));
	HR(mGrassFX->BeginPass(0));

	// Draw to depth buffer only.
	HR(mGrassMesh->DrawSubset(0));

	HR(mGrassFX->EndPass());
	HR(mGrassFX->End());

	mTerrain->draw();

	mWater->draw(); // draw alpha blended objects last.

	mGfxStats->display();

	HR(gd3dDevice->EndScene());

	// Present the backbuffer.
	HR(gd3dDevice->Present(0, 0, 0, 0));
}
Beispiel #10
0
void PropsDemo::buildGrass()
{
	D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
	UINT numElems = 0;
	HR(GrassVertex::Decl->GetDeclaration(elems, &numElems));

	HR(D3DXCreateMesh(NUM_GRASS_BLOCKS*2, NUM_GRASS_BLOCKS*4, D3DXMESH_MANAGED, 
		elems, gd3dDevice, &mGrassMesh));

	GrassVertex* v = 0;
	WORD* k = 0;
	HR(mGrassMesh->LockVertexBuffer(0, (void**)&v));
	HR(mGrassMesh->LockIndexBuffer(0, (void**)&k));

	int indexOffset = 0;

	// Scale down the region in which we generate grass.
	int w = (int)(mTerrain->getWidth() * 0.15f);
	int d = (int)(mTerrain->getDepth() * 0.15f);

	// Randomly generate a grass block (three intersecting quads) around the 
	// terrain in the height range [35, 50] (similar to the trees).
	for(int i = 0; i < NUM_GRASS_BLOCKS; ++i)
	{
		//============================================
		// Construct vertices.

		// Generate random position in region.  Note that we also shift
		// this region to place it in the world.
		float x = (float)((rand() % w) - (w*0.5f)) - 30.0f;
		float z = (float)((rand() % d) - (d*0.5f)) - 20.0f;
		float y = mTerrain->getHeight(x, z); 

		// Only generate grass blocks in this height range.  If the height
		// is outside this range, generate a new random position and 
		// try again.
		if(y < 37.0f || y > 40.0f)
		{
			--i; // We are trying again, so decrement back the index.
			continue;
		}

		float sx = GetRandomFloat(0.75f, 1.25f); 
		float sy = GetRandomFloat(0.75f, 1.25f);
		float sz = GetRandomFloat(0.75f, 1.25f);
		D3DXVECTOR3 pos(x, y, z);
		D3DXVECTOR3 scale(sx, sy, sz);

		buildGrassFin(v, k, indexOffset, pos, scale);
		v += 4;
		k += 6;
	}

	HR(mGrassMesh->UnlockVertexBuffer());
	HR(mGrassMesh->UnlockIndexBuffer());


	// Fill in the attribute buffer (everything in subset 0)
	DWORD* attributeBufferPtr = 0;
	HR(mGrassMesh->LockAttributeBuffer(0, &attributeBufferPtr));
	for(UINT i = 0; i < mGrassMesh->GetNumFaces(); ++i)
		attributeBufferPtr[i] = 0;
	HR(mGrassMesh->UnlockAttributeBuffer());

	DWORD* adj = new DWORD[mGrassMesh->GetNumFaces()*3];
	HR(mGrassMesh->GenerateAdjacency(EPSILON, adj));
	HR(mGrassMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT|D3DXMESHOPT_VERTEXCACHE,
		adj, 0, 0, 0));

	delete [] adj;
}
Beispiel #11
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;
}
Beispiel #12
0
void World::editTerrain()
{
	BOOL hit = false;
	DWORD faceIndex, hitCount;
	float u, v, dist;
	LPD3DXBUFFER allHits;
	ID3DXMesh* mesh = mTerrain->getMesh()->getMesh();

	if(gInput->keyDown(VK_LBUTTON) || gInput->keyDown(VK_RBUTTON))
	{
		float strength = 300.0f;
		if(gInput->keyDown(VK_RBUTTON))
			strength *= -1;  

		D3DXVECTOR3 origin, dir;
		gInput->getWorldPickingRay(origin, dir);

		D3DXIntersect(mesh, &origin, &dir, &hit, &faceIndex, &u, &v, &dist, &allHits, &hitCount);

		if(hit)
		{
			DWORD* k = 0;

			mesh->LockIndexBuffer(0, (void**)&k);
			int pressed = k[faceIndex*3];
			mesh->UnlockIndexBuffer();

			VertexPNT* v = 0;
			mesh->LockVertexBuffer(0, (void**)&v);

			int size = 10;

			int x = pressed % mTerrain->getColums();
			int z = pressed / mTerrain->getColums();

			for(int i = z - size/2; i < z + size/2; i++)
				for(int j = x - size/2; j < x + size/2; j++) {
					if(i < 0 || j < 0 || i >= mTerrain->getRows() || j >= mTerrain->getColums())
						continue;

					float dist = sqrt((float)(z-i)*(z-i) + (float)(x-j)*(x-j));
					dist = max(dist, 3.0f);

					if(strength > 0)
						v[i*mTerrain->getColums() + j].pos.y += min(strength / dist, strength)/100;
					else
						v[i*mTerrain->getColums() + j].pos.y += max(strength / dist, strength)/100;
				}

			mesh->UnlockVertexBuffer();

			//mTerrain->smothOut(x, z, 10);
		}
	}

	if(gInput->keyPressed(VK_MBUTTON)) {
		D3DXIntersect(mesh, &gCamera->getPosition(), &gCamera->getDirection(), &hit, &faceIndex, &u, &v, &dist, &allHits, &hitCount);

		if(hit)
		{
			DWORD* k = 0;

			mesh->LockIndexBuffer(0, (void**)&k);
			int pressed = k[faceIndex*3];
			mesh->UnlockIndexBuffer();

			VertexPNT* v = 0;
			mesh->LockVertexBuffer(0, (void**)&v);

			int size = 10;

			int x = pressed % mTerrain->getColums();
			int z = pressed / mTerrain->getColums();


			mTerrain->smothOut(x, z, 5);
		}
	}
}
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;
}
Beispiel #14
0
ID3DXMesh* GenerateSphere(IDirect3DDevice9* device, float radius, UINT rings, UINT sectors)
{
	if (!device)
	{
		return 0;
	}
	const DWORD numVertexes = rings * sectors;
	const DWORD numFaces = (rings - 1) * (sectors - 1) * 2;
    
    ID3DXMesh* mesh = 0;

    HRESULT hr = D3DXCreateMeshFVF(numFaces,
                      numVertexes,
                      D3DXMESH_32BIT | D3DXMESH_VB_WRITEONLY | D3DXMESH_IB_WRITEONLY,
                      D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1,
                      device,
                      &mesh);
    if (FAILED(hr))
    {
        MessageBox(0, L"Unable to generate sphere", L"Application error", MB_ICONSTOP);
        return 0;
    }
    SphereVertex* vertexes = 0;
    DWORD* indexes = 0;

    mesh->LockVertexBuffer(0, (void**)&vertexes);
    mesh->LockIndexBuffer(0, (void**)&indexes);


    float const R = 1.f / (float)(rings - 1);
    float const S = 1.f / (float)(sectors - 1);

    //
    for (UINT ring = 0; ring < rings; ring++)
    {
        for (UINT sector = 0; sector < sectors; sector++)
        {
            float const y = sin(D3DX_PI * 0.5f + D3DX_PI * ring * R );
            float const x = cos(2 * D3DX_PI * sector * S) * sin( D3DX_PI * ring * R );
            float const z = sin(2 * D3DX_PI * sector * S) * sin( D3DX_PI * ring * R );

            SphereVertex* vertex = vertexes++;

            vertex->pos = Vec3(x, y, z) * radius;
            //
            D3DXVec3Normalize(&vertex->normal, &vertex->pos);
            vertex->tex = Vec2(sector / (float)(sectors - 1.0f),
                               ring / (float)(rings - 1.0f));
        }
    }
    //
    for (UINT ring = 0; ring < rings - 1; ++ring)
    {
        for (UINT sector = 0; sector < sectors - 1; ++sector)
        {
            DWORD v0 = ring * sectors + sector;
            DWORD v1 = ring * sectors + sector + 1;
            DWORD v2 = (ring + 1) * sectors + sector;
            DWORD v3 = (ring + 1) * sectors + sector + 1;

            *indexes++ = v0;
            *indexes++ = v1;
            *indexes++ = v2;

            *indexes++ = v2;
            *indexes++ = v1;
            *indexes++ = v3;
        }
    }

    mesh->UnlockIndexBuffer();
    mesh->UnlockVertexBuffer();
    return mesh;
}
Beispiel #15
0
ID3DXMesh* CMesh::createD3DXMesh() const
{
    HRESULT hr;
    ID3DXMesh* dxMesh = 0;

    DWORD meshOpts = D3DXMESH_MANAGED;
    if( getIndexStride() == 4 )
        meshOpts |= D3DXMESH_32BIT;


    // get declaration
    D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
    UINT numElements;
    getVertexDecl().getObject()->GetDeclaration( decl, &numElements );
    // create mesh
    hr = D3DXCreateMesh( getIndexCount()/3, getVertexCount(), meshOpts, decl, &CD3DDevice::getInstance().getDevice(), &dxMesh );
    if( FAILED(hr) )
        return NULL;

    // copy VB
    {
        const void* srcVB = lockVBRead();
        void* dxVB = 0;
        hr = dxMesh->LockVertexBuffer( 0, &dxVB );
        if( FAILED(hr) ) {
            dxMesh->Release();
            return NULL;
        }
        memcpy( dxVB, srcVB, getVertexCount() * getVertexStride() );
        hr = dxMesh->UnlockVertexBuffer();
        unlockVBRead();
    }
    // copy IB
    {
        const void* srcIB = lockIBRead();
        void* dxIB = 0;
        hr = dxMesh->LockIndexBuffer( 0, &dxIB );
        if( FAILED(hr) ) {
            dxMesh->Release();
            return NULL;
        }
        memcpy( dxIB, srcIB, getIndexCount() * getIndexStride() );
        hr = dxMesh->UnlockIndexBuffer();
        unlockIBRead();
    }
    // copy groups
    {
        int ngroups = getGroupCount();
        D3DXATTRIBUTERANGE* attrs = new D3DXATTRIBUTERANGE[ngroups];
        DWORD* attrBuf = 0;
        hr = dxMesh->LockAttributeBuffer( 0, &attrBuf );
        if( FAILED(hr) ) {
            dxMesh->Release();
            return NULL;
        }
        for( int g = 0; g < ngroups; ++g ) {
            attrs[g].AttribId = g;
            const CMesh::CGroup& group = getGroup(g);
            attrs[g].VertexStart = group.getFirstVertex();
            attrs[g].VertexCount = group.getVertexCount();
            attrs[g].FaceStart = group.getFirstPrim();
            attrs[g].FaceCount = group.getPrimCount();
            for( int f = 0; f < group.getPrimCount(); ++f )
                *attrBuf++ = g;
        }
        dxMesh->UnlockAttributeBuffer();
        hr = dxMesh->SetAttributeTable( attrs, ngroups );
        delete[] attrs;
    }

    return dxMesh;
}
Beispiel #16
0
Mesh* GenerateCylinder(IDirect3DDevice9* device, float radius, float height, UINT sectors)
{
    if (!device)
	{
		return 0;
	}
	const DWORD numVertexes = 2 * (sectors + 1);
	const DWORD numFaces = 2 * sectors;
    
    ID3DXMesh* mesh = 0;

    HRESULT hr = D3DXCreateMeshFVF(numFaces,
                      numVertexes,
                      D3DXMESH_32BIT | D3DXMESH_VB_WRITEONLY | D3DXMESH_IB_WRITEONLY,
                      D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1,
                      device,
                      &mesh);
    if (FAILED(hr))
    {
        MessageBox(0, L"Unable to generate sphere", L"Application error", MB_ICONSTOP);
        return 0;
    }
    SphereVertex* vertexes = 0;
    DWORD* indexes = 0;

    mesh->LockVertexBuffer(0, (void**)&vertexes);
    mesh->LockIndexBuffer(0, (void**)&indexes);

    const UINT rings = 1;
    //
    for (UINT ring = 0; ring < rings + 1; ring++)
    {
        for (UINT sector = 0; sector < sectors + 1; sector++)
        {
            const float z = sinf(sector * D3DX_PI * 2.f / sectors) * radius;
            const float x = cosf(sector * D3DX_PI * 2.f / sectors) * radius ;
            const float y = height * (1.0f - (ring / rings));

            SphereVertex* vertex = vertexes++;
            vertex->pos = Vec3(x, y, z);
            vertex->normal = Vec3(x, 0, z);
            vertex->tex = Vec2((FLOAT)sector / (sectors - 1), (FLOAT)ring / rings );
        }
    }

    //
    for (UINT ring = 0; ring < rings; ++ring)
    {
        for (UINT sector = 0; sector < sectors; ++sector)
        {
            DWORD v0 = (ring * (sectors + 1) + sector);
            DWORD v1 = (ring * (sectors + 1) + sector + 1);
            DWORD v2 = ((ring + 1) * (sectors + 1) + sector);
            DWORD v3 = ((ring + 1) * (sectors + 1) + sector + 1);

            *indexes++ = v0;
            *indexes++ = v1;
            *indexes++ = v2;

            *indexes++ = v2;
            *indexes++ = v1;
            *indexes++ = v3;
        }
    }

    mesh->UnlockIndexBuffer();
    mesh->UnlockVertexBuffer();
    return mesh;
}
Beispiel #17
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();
}
Beispiel #18
0
void LoadXFile(
			   const std::string& filename, 
			   ID3DXMesh** meshOut,
			   std::vector<Mtrl>& mtrls, 
			   std::vector<IDirect3DTexture9*>& texs)
{
	// Step 1: Load the .x file from file into a system memory mesh.

	ID3DXMesh* meshSys      = 0;
	ID3DXBuffer* adjBuffer  = 0;
	ID3DXBuffer* mtrlBuffer = 0;
	DWORD numMtrls          = 0;

	HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM, gd3dDevice,
		&adjBuffer,	&mtrlBuffer, 0, &numMtrls, &meshSys));


	// Step 2: Find out if the mesh already has normal info?

	D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
	HR(meshSys->GetDeclaration(elems));

	bool hasNormals = false;
	D3DVERTEXELEMENT9 term = D3DDECL_END();
	for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
	{
		// Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}?
		if(elems[i].Stream == 0xff )
			break;

		if( elems[i].Type == D3DDECLTYPE_FLOAT3 &&
			elems[i].Usage == D3DDECLUSAGE_NORMAL &&
			elems[i].UsageIndex == 0 )
		{
			hasNormals = true;
			break;
		}
	}


	// Step 3: Change vertex format to VertexPNT.

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

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


	// Step 4: If the mesh did not have normals, generate them.

	if( hasNormals == false)
		HR(D3DXComputeNormals(meshSys, 0));


	// Step 5: Optimize the mesh.

	HR(meshSys->Optimize(D3DXMESH_MANAGED | 
		D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, 
		(DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut));
	ReleaseCOM(meshSys); // Done w/ system mesh.
	ReleaseCOM(adjBuffer); // Done with buffer.

	// Step 6: Extract the materials and load the textures.

	if( mtrlBuffer != 0 && numMtrls != 0 )
	{
		D3DXMATERIAL* d3dxmtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();

		for(DWORD i = 0; i < numMtrls; ++i)
		{
			// Save the ith material.  Note that the MatD3D property does not have an ambient
			// value set when its loaded, so just set it to the diffuse value.
			Mtrl m;
			m.ambient   = d3dxmtrls[i].MatD3D.Diffuse;
			m.diffuse   = d3dxmtrls[i].MatD3D.Diffuse;
			m.spec      = d3dxmtrls[i].MatD3D.Specular;
			m.specPower = d3dxmtrls[i].MatD3D.Power;
			mtrls.push_back( m );

			// Check if the ith material has an associative texture
			if( d3dxmtrls[i].pTextureFilename != 0 )
			{
				// Yes, load the texture for the ith subset
				IDirect3DTexture9* tex = 0;
				char* texFN = d3dxmtrls[i].pTextureFilename;
				HR(D3DXCreateTextureFromFile(gd3dDevice, texFN, &tex));

				// Save the loaded texture
				texs.push_back( tex );
			}
			else
			{
				// No texture for the ith subset
				texs.push_back( 0 );
			}
		}
	}
	ReleaseCOM(mtrlBuffer); // done w/ buffer
}
Beispiel #19
0
void XManager::loadXFile(IDirect3DDevice9* dev, const std::string& filename, ID3DXMesh** meshOut, std::vector<Material>* mtrls, std::vector<IDirect3DTexture9*>* texs) {
	// Step 1: Load the .x file from file into a system memory mesh.

	ID3DXMesh* meshSys      = 0;
	ID3DXBuffer* adjBuffer  = 0;
	ID3DXBuffer* mtrlBuffer = 0;
	DWORD numMtrls          = 0;

	HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM, dev,
		&adjBuffer,	&mtrlBuffer, 0, &numMtrls, &meshSys));


	// Step 2: Find out if the mesh already has normal info?

	D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
	HR(meshSys->GetDeclaration(elems));
	
	bool hasNormals = false;
	D3DVERTEXELEMENT9 term = D3DDECL_END();
	for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
	{
		// Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}?
		if(elems[i].Stream == 0xff )
			break;

		if( elems[i].Type == D3DDECLTYPE_FLOAT3 &&
			elems[i].Usage == D3DDECLUSAGE_NORMAL &&
			elems[i].UsageIndex == 0 )
		{
			hasNormals = true;
			break;
		}
	}


	// Step 3: Change vertex format to CustomVertex3NormalUV

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

	ID3DXMesh* temp = 0;
	HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM, 
		elements, dev, &temp));
	SAFERELEASECOM(meshSys);
	meshSys = temp;


	// Step 4: If the mesh did not have normals, generate them.

	if( hasNormals == false)
		HR(D3DXComputeNormals(meshSys, 0));


	// Step 5: Optimize the mesh.

	HR(meshSys->Optimize(D3DXMESH_MANAGED | 
		D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, 
		(DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut));
	SAFERELEASECOM(meshSys); // Done w/ system mesh.
	SAFERELEASECOM(adjBuffer); // Done with buffer.

	// Step 6: Extract the materials and load the textures.

	if( mtrlBuffer != 0 && numMtrls != 0 )
	{
		D3DXMATERIAL* d3dxmtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();

		for(DWORD i = 0; i < numMtrls; ++i)
		{
			// Save the ith material.  Note that the MatD3D property does not have an ambient
			// value set when its loaded, so just set it to the diffuse value.
			Material m;
			m.ambient   = d3dxmtrls[i].MatD3D.Diffuse;
			m.diffuse   = d3dxmtrls[i].MatD3D.Diffuse;
			m.spec      = d3dxmtrls[i].MatD3D.Specular;
			m.specPower = d3dxmtrls[i].MatD3D.Power;
			mtrls->push_back( m );

			// Check if the ith material has an associative texture
			if( d3dxmtrls[i].pTextureFilename != 0 )
			{
				IDirect3DTexture9* tex = 0;
				std::string s(d3dxmtrls[i].pTextureFilename);
				const char folder[] = "./texture/";
				unsigned int pos = s.find_last_of('\/');
				std::string newFileName(folder);

				// std::string::npos gets returned if no / was found
				if(pos != std::string::npos) {
					//std::string sub = s.substr(pos,s.size());

					if(strcmp(s.substr(pos+1,s.size()).c_str(),"Watcher.tga") == 0) {
						newFileName.append("Watcher_Black.tga");
					}
					else {
						newFileName.append(s.substr(pos+1,s.size()));
					}
				}
				else {
					
					newFileName.append(s);
					
				}
				// Save the loaded texture
				HR(D3DXCreateTextureFromFile(dev, newFileName.c_str(), &tex));
				texs->push_back( tex );
			}
			else
			{
Beispiel #20
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);
}
void CMeshConverter::OptimiseGraphicsObject(void)
{
	int						i;
	int						j;
	ID3DXMesh*				pXMesh;
	CGraphicsPrimitive*		pcPrimitive;
	CVertexBufferExtended*	psVertexBuffer;
	void*					pvDestIndexBuffer;
	void*					pvDestVertexBuffer;
	void*					pvSrcIndexBuffer;
	void*					pvSrcVertexBuffer;
	int						iVertSize;
	DWORD*					pvAdjacency;
	int						iPrimitiveStart;
	int						iOldVertSize;
	int						iNumIndices;
	int						iOldVertexBufferIndex;
	int						iNumTriangles;
	void*					pvDestBaseIndexBuffer;
	SIndexBuffer*			psIndexBuffer;
	DWORD					iMeshOptions;

	mpcGraphicsObject->SortPrimitives();
	mpcGraphicsObject->Lock();
	psIndexBuffer = mpcGraphicsObject->GetIndexBuffer();
	iVertSize = 0;
	iNumIndices = 0;
	iOldVertexBufferIndex = 0;
	iNumTriangles = 0;
	iOldVertSize = 0;
	iMeshOptions = D3DXMESH_SYSTEMMEM;
	SetFlag((int*)&iMeshOptions, D3DXMESH_32BIT, psIndexBuffer->iIndexSize == 4);
	for (i = 0; i < mpcGraphicsObject->GetNumPrimitives(); i++)
	{
		pcPrimitive = mpcGraphicsObject->GetPrimitive(i);
		psVertexBuffer = mpcGraphicsObject->GetVertexBufferForIndex(pcPrimitive->miVertexBufferIndex);

		if (iOldVertSize != psVertexBuffer->iVertexSize)
		{
			if (iNumIndices != 0)
			{
				gcD3D.CreateMesh(iNumTriangles, iNumIndices, iMeshOptions, psVertexBuffer->iVertexFormat, &pXMesh);
				iVertSize = pXMesh->GetNumBytesPerVertex();
				pXMesh->LockIndexBuffer(D3DLOCK_NO_DIRTY_UPDATE, &pvDestBaseIndexBuffer);
				pXMesh->LockVertexBuffer(D3DLOCK_NO_DIRTY_UPDATE, &pvDestVertexBuffer);

				psVertexBuffer = mpcGraphicsObject->GetVertexBufferForIndex(iOldVertexBufferIndex);
				pvSrcVertexBuffer = psVertexBuffer->pvLockedBuffer;

				if (iVertSize != psVertexBuffer->iVertexSize)
				{
					gcLogger.Error("D3DX vertex size differs from expected size");
					break;
				}

				memcpy(pvDestVertexBuffer, pvSrcVertexBuffer, psVertexBuffer->iVertexSize * psVertexBuffer->iNumVerticies);

				pvDestIndexBuffer = pvDestBaseIndexBuffer;
				for (j = iPrimitiveStart; j < i; j++)
				{
					pcPrimitive = mpcGraphicsObject->GetPrimitive(j);
					pvSrcIndexBuffer = RemapSinglePointer(psIndexBuffer->pvLockedBuffer, 2 * pcPrimitive->miStartIndex);
					memcpy(pvDestIndexBuffer, pvSrcIndexBuffer, psIndexBuffer->iIndexSize * pcPrimitive->miNumVertices);
					pvDestIndexBuffer = RemapSinglePointer(pvDestIndexBuffer, pcPrimitive->miNumVertices);
				}

				pvAdjacency = (DWORD*)malloc(pcPrimitive->miNumPrimitives * 3 * sizeof(DWORD));
				pXMesh->GenerateAdjacency(0.0f, pvAdjacency);
				pXMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_DONOTSPLIT, pvAdjacency, NULL, NULL, NULL);
				free(pvAdjacency);

				pvDestIndexBuffer = pvDestBaseIndexBuffer;
				for (j = iPrimitiveStart; j < i; j++)
				{
					pcPrimitive = mpcGraphicsObject->GetPrimitive(j);
					pvSrcIndexBuffer = RemapSinglePointer(psIndexBuffer->pvLockedBuffer, 2 * pcPrimitive->miStartIndex);
					memcpy(pvSrcIndexBuffer, pvDestIndexBuffer, psIndexBuffer->iIndexSize * pcPrimitive->miNumVertices);
					pvDestIndexBuffer = RemapSinglePointer(pvDestIndexBuffer, pcPrimitive->miNumVertices);
				}

				memcpy(pvSrcVertexBuffer, pvDestVertexBuffer, psVertexBuffer->iVertexSize * psVertexBuffer->iNumVerticies);

				pXMesh->UnlockIndexBuffer();
				pXMesh->UnlockVertexBuffer();
				pXMesh->Release();
			}
			iPrimitiveStart = i;
			iNumIndices = 0;
			iOldVertexBufferIndex = pcPrimitive->miVertexBufferIndex;
		}
		else
		{
			iNumIndices += pcPrimitive->miNumVertices;
			iNumTriangles += pcPrimitive->miNumPrimitives;
			if (iOldVertexBufferIndex != pcPrimitive->miVertexBufferIndex)
			{
				gcUserError.Set("Primitive vertex buffer index is F****D!");
				break;
			}
		}
	}
	mpcGraphicsObject->Unlock();
}
Beispiel #22
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;
}
Beispiel #23
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;
}
Beispiel #24
0
void RobotArmDemo::drawScene()
{
	// Clear the backbuffer and depth buffer.
	HR(gd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0));

	HR(gd3dDevice->BeginScene());

	HR(mFX->SetValue(mhLight, &mLight, sizeof(DirLight)));

	HR(mFX->SetTechnique(mhTech));
	UINT numPasses = 0;
	HR(mFX->Begin(&numPasses, 0));
	HR(mFX->BeginPass(0));

	// Build the world transforms for each bone, then render them.
	buildBoneWorldTransforms();
	D3DXMATRIX T;
	D3DXMatrixTranslation(&T, -NUM_BONES, 0.0f, 0.0f);
	for(int i = 0; i < NUM_BONES; ++i)
	{
		// Append the transformation with a slight translation to better
		// center the skeleton at the center of the scene.
		mWorld = mBones[i].toWorldXForm * T;
		HR(mFX->SetMatrix(mhWorld, &mWorld));

		HR(mFX->SetMatrix(mhWVP, &(mWorld*mView*mProj)));
		D3DXMATRIX worldInvTrans;
		//! ÄæÏò
		D3DXMatrixInverse(&worldInvTrans, 0, &mWorld);
		//! תÖÃ
		D3DXMatrixTranspose(&worldInvTrans, &worldInvTrans);
		HR(mFX->SetMatrix(mhWorldInvTrans, &worldInvTrans));
		for(int j = 0; j < mMtrl.size(); ++j)
		{
			HR(mFX->SetValue(mhMtrl, &mMtrl[j], sizeof(Mtrl)));

			// If there is a texture, then use.
			if(mTex[j] != 0)
			{
				HR(mFX->SetTexture(mhTex, mTex[j]));
			}

			// But if not, then set a pure white texture.  When the texture color
			// is multiplied by the color from lighting, it is like multiplying by
			// 1 and won't change the color from lighting.
			else
			{
				HR(mFX->SetTexture(mhTex, mWhiteTex));
			}

			HR(mFX->CommitChanges());
			HR(mBoneMesh->DrawSubset(j));
		}
	}

	HR(mFX->EndPass());
	HR(mFX->End());

	mGfxStats->display();

	HR(gd3dDevice->EndScene());

	// Present the backbuffer.
	HR(gd3dDevice->Present(0, 0, 0, 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);
}
Beispiel #26
0
// Create a torus with the parameters specified
// Returns true for success, false otherwise
bool CreateTorus(float innerRad, float outerRad, int color, ID3DXMesh **mesh)
{
    assert(g3D->mDevice != NULL);
    assert(mesh != NULL);

    const unsigned int kSides = 16; // Number of divisions looking at the torus form the side
    const unsigned int kRings = 16; // Number of divisions looking at the torus from the top
    // so you can see the hole in the middle

    ID3DXMesh *temp = NULL; // Temp D3D mesh object

    // Create the torus
    // By paramter:
    // g3D->mDevice -- Pointer to the Direct3D device to be associated with the torus
    // innerRad -- Inner radius of the torus
    // outerRad -- Outside radius of the torus
    // kSides -- Number of sides in a cross-section of the torus
    // kRings -- Number of rings in a cross-section of the torus
    // &temp -- A pointer to a ID3DXMesh*, it will get filled with the
    //			the created mesh
    // NULL --  Optional pointer to a ID3DXBuffer, if a valid pointer was passed
    //			it would be filled with the adjacency information for each face in
    //			the mesh.  By passing NULL, we say we don't want this information
    if(D3DXCreateTorus(g3D->mDevice, innerRad, outerRad, kSides, kRings, &temp, NULL) != D3D_OK)
        return false;

    // Next we clone the mesh.  This does two things.  First, it allows us to
    // specify the vertex format we want on the cloned mesh.  Second, it copies the
    // current mesh data into the ID3DXMesh we passed to this function.
    // By parameter:
    // D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED -- Flags specifying how we want the mesh to be
    //												cloned.  This particular flag combo says
    //												"Have the vertex buffer and index buffer
    //												associated with this mesh be in pooled memory
    //												that DirectX manages for us."
    // SVertexType -- Flexible vertex format that we want the cloned mesh to be converted to
    // g3D->mDevice -- IDirect3DDevice9 to associate this mesh with
    // mesh -- A pointer to a ID3DXMesh* that will get filled with the cloned mesh
    if(temp->CloneMeshFVF(D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED, SVertexType,
                          g3D->mDevice, mesh) != D3D_OK)
    {
        return false;
    }

    // Okay so up to this point we've created a stock D3D torus, then converted
    // it a torus with the FVF that we want.  Now were going to loop through each
    // vertex and set it to the color that we want it to be.

    SVertex *v;

    // Lock the vertex buffer
    if((*mesh)->LockVertexBuffer(0, (void**)&v) != D3D_OK)
    {
        (*mesh)->Release();
        return false;
    }

    // Loop through all the verts in the mesh, setting each one's
    // color to the color passed into the function
    for(unsigned int i = 0; i < (*mesh)->GetNumVertices(); ++i)
        v[i].color = color;

    // We're done with the vertex buffer, so unlock it so it may be used
    // by others
    (*mesh)->UnlockVertexBuffer();

    temp->Release(); // Last but not least, free up the temporary mesh
    return true;
}
Beispiel #27
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);
}