Creating the Scene

The CreateScene function creates the elements making up the 3-D scene. In this sample, the scene consists of a single light, the viewport, the background and surface materials, the three transformation matrices, and the execute buffer holding the state changes and drawing primitives.

static HRESULT 
CreateScene(void) 
{ 
    HRESULT              hRes; 
    D3DMATERIAL          d3dMaterial; 
    D3DLIGHT             d3dLight; 
    DWORD                dwVertexSize; 
    DWORD                dwInstructionSize; 
    DWORD                dwExecuteBufferSize; 
    D3DEXECUTEBUFFERDESC d3dExecuteBufferDesc; 
    D3DEXECUTEDATA       d3dExecuteData; 
 
    ASSERT(NULL != lpd3d); 
    ASSERT(NULL != lpd3dDevice); 
    ASSERT(NULL == lpd3dViewport); 
    ASSERT(NULL == lpd3dMaterial); 
    ASSERT(NULL == lpd3dBackgroundMaterial); 
    ASSERT(NULL == lpd3dExecuteBuffer); 
    ASSERT(NULL == lpd3dLight); 
    ASSERT(0  == hd3dWorldMatrix); 
    ASSERT(0  == hd3dViewMatrix); 
    ASSERT(0  == hd3dProjMatrix); 
 
    // Create the light. 
 
    hRes = lpd3d->lpVtbl->CreateLight(lpd3d, &lpd3dLight, NULL); 
    if (FAILED(hRes)) 
        return hRes; 
 
    ZeroMemory(&d3dLight, sizeof(d3dLight)); 
    d3dLight.dwSize = sizeof(d3dLight); 
    d3dLight.dltType = D3DLIGHT_POINT; 
    d3dLight.dcvColor.dvR    = D3DVAL( 1.0); 
    d3dLight.dcvColor.dvG    = D3DVAL( 1.0); 
    d3dLight.dcvColor.dvB    = D3DVAL( 1.0); 
    d3dLight.dcvColor.dvA    = D3DVAL( 1.0); 
    d3dLight.dvPosition.dvX  = D3DVAL( 1.0); 
    d3dLight.dvPosition.dvY  = D3DVAL(-1.0); 
    d3dLight.dvPosition.dvZ  = D3DVAL(-1.0); 
    d3dLight.dvAttenuation0  = D3DVAL( 1.0); 
    d3dLight.dvAttenuation1  = D3DVAL( 0.1); 
    d3dLight.dvAttenuation2  = D3DVAL( 0.0); 
    hRes = lpd3dLight->lpVtbl->SetLight(lpd3dLight, &d3dLight); 
    if (FAILED(hRes)) 
        return hRes; 
 
    // Create the background material. 
 
    hRes = lpd3d->lpVtbl->CreateMaterial(lpd3d, 
        &lpd3dBackgroundMaterial, NULL); 
    if (FAILED(hRes)) 
        return hRes; 
 
    ZeroMemory(&d3dMaterial, sizeof(d3dMaterial)); 
    d3dMaterial.dwSize = sizeof(d3dMaterial); 
    d3dMaterial.dcvDiffuse.r  = D3DVAL(0.0); 
    d3dMaterial.dcvDiffuse.g  = D3DVAL(0.0); 
    d3dMaterial.dcvDiffuse.b  = D3DVAL(0.0); 
    d3dMaterial.dcvAmbient.r  = D3DVAL(0.0); 
    d3dMaterial.dcvAmbient.g  = D3DVAL(0.0); 
    d3dMaterial.dcvAmbient.b  = D3DVAL(0.0); 
    d3dMaterial.dcvSpecular.r = D3DVAL(0.0); 
    d3dMaterial.dcvSpecular.g = D3DVAL(0.0); 
    d3dMaterial.dcvSpecular.b = D3DVAL(0.0); 
    d3dMaterial.dvPower       = D3DVAL(0.0); 
 
    // Since this is the background material, we don't want a ramp to be 
    // allocated. (We will not be smooth-shading the background.) 
 
    d3dMaterial.dwRampSize    = 1; 
 
    hRes = lpd3dBackgroundMaterial->lpVtbl->SetMaterial 
        (lpd3dBackgroundMaterial, &d3dMaterial); 
    if (FAILED(hRes)) 
        return hRes; 
    hRes = lpd3dBackgroundMaterial->lpVtbl->GetHandle 
        (lpd3dBackgroundMaterial, lpd3dDevice, &hd3dBackgroundMaterial); 
    if (FAILED(hRes)) 
        return hRes; 
 
    // Create the viewport. 
    // The viewport parameters are set in the UpdateViewport function, 
    // which is called in response to WM_SIZE. 
 
    hRes = lpd3d->lpVtbl->CreateViewport(lpd3d, &lpd3dViewport, NULL); 
    if (FAILED(hRes)) 
        return hRes; 
    hRes = lpd3dDevice->lpVtbl->AddViewport(lpd3dDevice, lpd3dViewport); 
    if (FAILED(hRes)) 
        return hRes; 
    hRes = lpd3dViewport->lpVtbl->SetBackground(lpd3dViewport, 
        hd3dBackgroundMaterial); 
    if (FAILED(hRes)) 
        return hRes; 
    hRes = lpd3dViewport->lpVtbl->AddLight(lpd3dViewport, lpd3dLight); 
    if (FAILED(hRes)) 
        return hRes; 
 
    // Create the matrices. 
 
    hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice, 
        &hd3dWorldMatrix); 
    if (FAILED(hRes)) 
        return hRes; 
    hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dWorldMatrix, 
        &d3dWorldMatrix); 
    if (FAILED(hRes)) 
        return hRes; 
    hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice, 
        &hd3dViewMatrix); 
    if (FAILED(hRes)) 
        return hRes; 
    hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dViewMatrix, 
        &d3dViewMatrix); 
    if (FAILED(hRes)) 
        return hRes; 
    hRes = lpd3dDevice->lpVtbl->CreateMatrix(lpd3dDevice, 
        &hd3dProjMatrix); 
    if (FAILED(hRes)) 
        return hRes; 
    SetPerspectiveProjection(&d3dProjMatrix, HALF_HEIGHT, FRONT_CLIP, 
        BACK_CLIP); 
    hRes = lpd3dDevice->lpVtbl->SetMatrix(lpd3dDevice, hd3dProjMatrix, 
        &d3dProjMatrix); 
    if (FAILED(hRes)) 
        return hRes; 
 
    // Create the surface material. 
 
    hRes = lpd3d->lpVtbl->CreateMaterial(lpd3d, &lpd3dMaterial, NULL); 
    if (FAILED(hRes)) 
        return hRes; 
    ZeroMemory(&d3dMaterial, sizeof(d3dMaterial)); 
    d3dMaterial.dwSize = sizeof(d3dMaterial); 
 
    // Base green with white specular. 
 
    d3dMaterial.dcvDiffuse.r  = D3DVAL(0.0); 
    d3dMaterial.dcvDiffuse.g  = D3DVAL(1.0); 
    d3dMaterial.dcvDiffuse.b  = D3DVAL(0.0); 
    d3dMaterial.dcvAmbient.r  = D3DVAL(0.0); 
    d3dMaterial.dcvAmbient.g  = D3DVAL(0.4); 
    d3dMaterial.dcvAmbient.b  = D3DVAL(0.0); 
    d3dMaterial.dcvSpecular.r = D3DVAL(1.0); 
    d3dMaterial.dcvSpecular.g = D3DVAL(1.0); 
    d3dMaterial.dcvSpecular.b = D3DVAL(1.0); 
    d3dMaterial.dvPower       = D3DVAL(20.0); 
    d3dMaterial.dwRampSize    = 16; 
 
    hRes = lpd3dMaterial->lpVtbl->SetMaterial(lpd3dMaterial, 
        &d3dMaterial); 
    if (FAILED(hRes)) 
        return hRes; 
 
    hRes = lpd3dMaterial->lpVtbl->GetHandle(lpd3dMaterial, lpd3dDevice, 
        &hd3dSurfaceMaterial); 
    if (FAILED(hRes)) 
        return hRes; 
 
    // Build the execute buffer. 
 
    dwVertexSize      = (NUM_VERTICES        * sizeof(D3DVERTEX)); 
    dwInstructionSize = (NUM_INSTRUCTIONS    * sizeof(D3DINSTRUCTION)) + 
                        (NUM_STATES          * sizeof(D3DSTATE))       + 
                        (NUM_PROCESSVERTICES * 
                                        sizeof(D3DPROCESSVERTICES))    + 
                        (NUM_TRIANGLES      * sizeof(D3DTRIANGLE)); 
    dwExecuteBufferSize = dwVertexSize + dwInstructionSize; 
    ZeroMemory(&d3dExecuteBufferDesc, sizeof(d3dExecuteBufferDesc)); 
    d3dExecuteBufferDesc.dwSize       = sizeof(d3dExecuteBufferDesc); 
    d3dExecuteBufferDesc.dwFlags      = D3DDEB_BUFSIZE; 
    d3dExecuteBufferDesc.dwBufferSize = dwExecuteBufferSize; 
    hRes = lpd3dDevice->lpVtbl->CreateExecuteBuffer(lpd3dDevice, 
        &d3dExecuteBufferDesc, &lpd3dExecuteBuffer, NULL); 
    if (FAILED(hRes)) 
        return hRes; 
 
    // Fill the execute buffer with the required vertices, state 
    // instructions and drawing primitives. 
 
    hRes = FillExecuteBuffer(); 
    if (FAILED(hRes)) 
        return hRes; 
 
    // Set the execute data so Direct3D knows how many vertices are in 
    // the buffer and where the instructions start. 
 
    ZeroMemory(&d3dExecuteData, sizeof(d3dExecuteData)); 
    d3dExecuteData.dwSize = sizeof(d3dExecuteData); 
    d3dExecuteData.dwVertexCount       = NUM_VERTICES; 
    d3dExecuteData.dwInstructionOffset = dwVertexSize; 
    d3dExecuteData.dwInstructionLength = dwInstructionSize; 
    hRes = lpd3dExecuteBuffer->lpVtbl->SetExecuteData 
        (lpd3dExecuteBuffer, &d3dExecuteData); 
    if (FAILED(hRes)) 
        return hRes; 
 
    return DD_OK; 
}