⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tunnel.cpp

📁 国外游戏开发者杂志1997年第九期配套代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        joint[spoke] = D3DVERTEX(p + pt * TUBE_R, -pt,
                                 1.0f - theta / (float) (2.0f * PI), tv);
	}
}


/*
 * Defines the triangles which form a segment between ring1 and ring2 and
 * stores them at lpTri.  lpTri must be pre-allocated.
 */
void 
MakeSegment(int ring1, int ring2, LPD3DTRIANGLE lpTri)
{
    int side, triangle = 0;

    for (side = 0; side < SIDES; side++) {
        /*
         * Each side consists of two triangles.
         */
        lpTri[triangle].v1 = ring1 * SIDES + side;
        lpTri[triangle].v2 = ring2 * SIDES + side;
        lpTri[triangle].v3 = ring2 * SIDES + ((side + 1) % SIDES);
        
        /*
         * for wireframe only need first two edges.
         * Start a two triangle flat fan for each tunnel face.
         */
                
        lpTri[triangle].wFlags = D3DTRIFLAG_STARTFLAT(1);
        lpTri[triangle].wFlags |= D3DTRIFLAG_EDGEENABLE1 |
                                  D3DTRIFLAG_EDGEENABLE2;
        
        triangle++;
        lpTri[triangle].v2 = ring2 * SIDES + ((side + 1) % SIDES);
        lpTri[triangle].v3 = ring1 * SIDES + ((side + 1) % SIDES);
        lpTri[triangle].v1 = ring1 * SIDES + side;
        
        /*
         * Dont need any edges for wireframe.
         */
        lpTri[triangle].wFlags = D3DTRIFLAG_EVEN;
        
        triangle++;
    }
}


/*
 * Creates a new segment of the tunnel at the current end position.
 * Creates a new ring and segment.
 */
void 
UpdateTubeInMemory(void)
{
    static int texRing = 0; /* Static counter defining the position of
                             * this ring on the texture.
                             */
    int endRing; /* The ring at the end of the tube in memory. */
    int RingOffset, SegmentOffset; /* Offsets into the vertex and triangle 
                                    * lists for the new data.
                                    */
    /*
     * Replace the back ring with a new ring at the front of the tube
     * in memory.
     */
    memmove(&tube.lpV[SIDES], &tube.lpV[0], sizeof(tube.lpV[0]) * (NUM_V - SIDES));
    MakeRing(tube.endP, tube.endD, tube.endN, texRing/(float)TEX_RINGS,
             &tube.lpV[0]);
    /*
     * Replace the back segment with a new segment at the front of the
     * tube in memory. Update the current end position of the tube in
     * memory.
     */
    endRing = (tube.currentRing + SEGMENTS) % (SEGMENTS + 1);
    MoveToPosition(tube.endPos, &tube.endP, &tube.endD, &tube.endN);
    /*
     * Update the execute buffer with the new vertices and triangles.
     */
    RingOffset = sizeof(D3DVERTEX) * tube.currentRing * SIDES;
    SegmentOffset = sizeof(D3DTRIANGLE) * tube.currentSegment * SIDES * 2;
    memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
    debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
    if (lpD3DExBuf->Lock(&debDesc) != D3D_OK)
        return;
    memcpy((char *) debDesc.lpData,
           &tube.lpV[0], sizeof(D3DVERTEX) * NUM_V);
    lpD3DExBuf->Unlock();
    /*
     * Update the position of the back of the tube in memory and texture
     * counter.
     */
    tube.currentRing = (tube.currentRing + 1) % (SEGMENTS + 1);
    tube.currentSegment = (tube.currentSegment + 1) % SEGMENTS;
    texRing = (texRing + 1) % TEX_RINGS;
}


/*
 * Move the camera through the tunnel.  Create new segments of the tunnel
 * when the camera gets close to the end of the section in memory.
 */
void 
MoveCamera(LPDIRECT3DDEVICE lpDev, LPDIRECT3DVIEWPORT lpView)
{
    /*
     * Update the position on curve and camera vectors.
     */
    tube.cameraPos += (float)SPEED;
    if (tube.cameraPos > PATH_LENGTH)
        tube.cameraPos -= PATH_LENGTH;
    MoveToPosition(tube.cameraPos, &tube.cameraP, &tube.cameraD,
                   &tube.cameraN);
    /*
     * If the camera is close to the end, add a new segment.
     */
    if (tube.endPos - tube.cameraPos < DEPTH) {
        tube.endPos = tube.endPos + (float)SEGMENT_LENGTH;
        if (tube.endPos > PATH_LENGTH)
            tube.endPos -= PATH_LENGTH;
        UpdateTubeInMemory();
    }
}


// update the location of the spot in camera space
// need to be executed only if are NOT in the SCREEN_COORDINATES mode
// or we use the BLT_COMPOSITE method

void updateSWPolygon()
{
#ifndef SCREEN_COORDINATES
	if( compositeMethod  ==  TEXTUREMAP_COMPOSITE)  {
		moveSWPolygon();
        memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
        debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
	if (lpD3DExBufSpot->Lock(&debDesc) != D3D_OK)
        return;
    memcpy((char *) debDesc.lpData, &src_v[0], sizeof(D3DTLVERTEX) * NUM_VERTICES_SPOT);
    lpD3DExBufSpot->Unlock();
    }
#endif
}

/*
 * Modify the buffer between rendering frames
 */
static void 
TickScene(LPDIRECT3DDEVICE lpDev, LPDIRECT3DVIEWPORT lpView)
{
    MoveCamera(lpDev, lpView);
    updateSWPolygon();
}

/*
 * Each frame, renders the scene and calls TickScene to modify the object
 * for the next frame.
 */
BOOL
RenderScene(LPDIRECT3DDEVICE lpDev, LPDIRECT3DVIEWPORT lpView,
            LPD3DRECT lpExtent)
{
    HRESULT ddrval;
	BOOL loadResult;
/*
 * Move the camera by updating the view matrix and move the light.
 */
    PositionCamera(&tube.cameraP, &tube.cameraD, &tube.cameraN, &view);
    ddrval = lpDev->SetMatrix(hView, &view);
    if (ddrval != D3D_OK)
        return FALSE;
    tube.light.dvPosition = tube.cameraP;
    ddrval = tube.lpD3DLight->SetLight(&tube.light);
    if (ddrval != D3D_OK)
        return FALSE;
    
    if( compositeMethod  ==  TEXTUREMAP_COMPOSITE) 
	{

	// Here is one of the synchronization calls.
    // The timeout is 1 second so at least it would move if deadlock were possible
	WaitForSingleObject(eventHandle, 1000);
    // OK, now reset the event and go onto the composite
    ResetEvent(eventHandle);
	
	// now we add the quads drawn by the SW thread to the statistics
	sw_quads_drawn += sw_quads_per_frame ;
	
	// Switch the active and the develope buffers and continue
	lpDDTempSurfaceSystem     = lpDDActiveSurfaceSystem;
    lpDDActiveSurfaceSystem   = lpDDDevelopSurfaceSystem;
    lpDDDevelopSurfaceSystem  = lpDDTempSurfaceSystem;

    // Resume the SW Thread - that is, the main thread has consumed the
    // output of the SW rendering.  
	// We Use double buffering so letting the  SW to go ahead to the next frame early
	SetEvent(compositeHandle);
    // Load texture from the SW thread to be used in the HW scene in the next frame.
   loadResult =  LoadTextureFromSW();
   if(! loadResult)  
		  return FALSE; 
	/* * Execute the instruction buffer and update the view  */
    ddrval = lpDev->BeginScene();
    if (ddrval != D3D_OK)
        return FALSE;
    ddrval = lpDev->Execute(lpD3DExBuf, lpView, D3DEXECUTE_CLIPPED);
             if (ddrval != D3D_OK)    return FALSE;
     ddrval = lpDev->Execute(lpD3DExBufSpot, lpView, D3DEXECUTE_UNCLIPPED);
			 if (ddrval != D3D_OK)   { 
				 char * error_str = D3DAppErrorToString(ddrval);
                 Msg(error_str,0);
                 return FALSE;
			 }
    ddrval = lpDev->EndScene();
			 if (ddrval != D3D_OK)    return FALSE;
    ddrval = lpD3DExBuf->GetExecuteData(&d3dExData);
			 if (ddrval != D3D_OK)    return FALSE;
    ddrval = lpD3DExBufSpot->GetExecuteData(&d3dExDataSpot);
			if (ddrval != D3D_OK)    return FALSE;
	*lpExtent = d3dExData.dsStatus.drExtent;
	}
	else   //   compositeMethod  == BLT_COMPOSITE) 
	{
    /* * Execute the instruction buffer and update the view  */
    ddrval = lpDev->BeginScene();
    if (ddrval != D3D_OK)
        return FALSE;
    ddrval = lpDev->Execute(lpD3DExBuf, lpView, D3DEXECUTE_CLIPPED);
             if (ddrval != D3D_OK)    return FALSE;
    ddrval = lpDev->EndScene();
			 if (ddrval != D3D_OK)    return FALSE;
    ddrval = lpD3DExBuf->GetExecuteData(&d3dExData);
			 if (ddrval != D3D_OK)    return FALSE;
	*lpExtent = d3dExData.dsStatus.drExtent;
    // Here is one of the synchronization calls.
    // The timeout is 1 second so at least it would move if deadlock were possible
	WaitForSingleObject(eventHandle, 1000);
    // OK, now reset the event and go onto the composite
    ResetEvent(eventHandle);
	
	// now we add the quads drawn by the SW thread to the statistics
	sw_quads_drawn += sw_quads_per_frame ;
   }
	/*
     * Modify for the next time around
     */
    TickScene(lpDev, lpView);
    return TRUE;
}

void
OverrideDefaults(Defaults* defaults)
{
    defaults->rs.bZBufferOn = FALSE;
    defaults->rs.bPerspCorrect = TRUE;
    defaults->bClearsOn = FALSE;
    lstrcpy(defaults->Name, "Tunnel D3D Example");
}

BOOL
InitScene(void)
{
    float position;             /* Curve position counter. */
    int i;                      /* counter */

    /*
     * Reserved memory for vertices, triangles and spline points.
     */
    tube.lpV = (LPD3DVERTEX) malloc(sizeof(D3DVERTEX) * NUM_V);
    tube.lpTri = (LPD3DTRIANGLE) malloc(sizeof(D3DTRIANGLE) * NUM_TRI);
    tube.lpPoints = (LPD3DVECTOR) malloc(sizeof(D3DVECTOR)*SPLINE_POINTS);
    /*
     * Generate spline points
     */
    for (i = 0; i < SPLINE_POINTS; i++) {
        tube.lpPoints[i].x = (float)(cos(i * 4.0) * 20.0);
        tube.lpPoints[i].y = (float)(sin(i * 4.0) * 20.0);
        tube.lpPoints[i].z = i * 20.0f;
    }
    /*
     * Create the initial tube section in memory.
     */
    tube.endN.x = (float)0.0;
    tube.endN.y = (float)1.0;
    tube.endN.z = (float)0.0;
    position = (float)0.0;
    for (i = 0; i < SEGMENTS + 1; i++) {
        MoveToPosition(position, &tube.endP, &tube.endD, &tube.endN);
        position += (float)SEGMENT_LENGTH;
        MakeRing(tube.endP, tube.endD, tube.endN, 
                 (float)(i % TEX_RINGS) / TEX_RINGS,
                 &tube.lpV[(SEGMENTS - i) * SIDES]);
    }
    for (i = 0; i < SEGMENTS; i++)
        MakeSegment(i + 1, i, &tube.lpTri[i * SIDES * 2]);
    /*
     * Move the camera to the begining and set some globals
     */
    tube.cameraN.x = (float)0.0;
    tube.cameraN.y = (float)1.0;
    tube.cameraN.z = (float)0.0;
    MoveToPosition((float)0.0, &tube.cameraP, &tube.cameraD, &tube.cameraN);
	tube.currentRing = 0;
    tube.currentSegment = 0;
    tube.cameraPos = (float)0.0;
    tube.endPos = position;
    
    #if defined(SW_SPOT)
	initSwSpot();
    upVec.x = (float)0.0;
    upVec.y = (float)1.0;
    upVec.z = (float)0.0;
    #ifndef SCREEN_COORDINATES
     moveSWPolygon();
    #endif
#endif
	return TRUE;
}

void
ReleaseScene(void)
{
    if (tube.lpPoints)
        free(tube.lpPoints);
    if (tube.lpTri)
        free(tube.lpTri);
    if (tube.lpV)
        free(tube.lpV);
}
 
void
ReleaseView(LPDIRECT3DVIEWPORT lpView)
{
    if (lpView)
        lpView->DeleteLight(tube.lpD3DLight);
    RELEASE(lpD3DExBuf);
    RELEASE(tube.lpD3DLight);
    RELEASE(lpmat);
    RELEASE(lpbmat);
#if defined(SW_SPOT)
    RELEASE(lpD3DExBufSpot);
#endif  
}


/*
 * Builds the scene and initializes the execute buffer for rendering.
 * Returns 0 on failure.
 */
BOOL
InitView(LPDIRECTDRAW lpDD, LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpDev, 
           LPDIRECT3DVIEWPORT lpView, int NumTextures, 
           LPD3DTEXTUREHANDLE TextureHandle)
{
    /* Variables for exectue buffer generation */
    LPVOID lpBufStart, lpInsStart, lpPointer;
    LPDIRECT3DEXECUTEBUFFER lpD3DExCmdBuf;
    DWORD size;

    /* Background material variables */
    D3DMATERIAL bmat;
    D3DMATERIALHANDLE hbmat;
    D3DMATERIAL mat;

    /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -