//----------------------------------------------------------------------------- // File: Dolphin.cpp // // Desc: Sample of swimming dolphin // // Note: This code uses the D3D Framework helper library. // // Copyright (c) 1998-1999 Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #include "stdafx.h" #define D3D_OVERLOADS #include "StdAfx.h" #include #include #include "D3DApp.h" #include "D3DUtil.h" #include "D3DMath.h" #include "D3DTextr.h" #include "D3DFile.h" #include #include //#include #include "dxsvr.h" #include "sealife.h" float rnd(void) { return float(rand())/RAND_MAX; } //----------------------------------------------------------------------------- // Name: CSeaLife() // Desc: Constructor //----------------------------------------------------------------------------- /* */ CSeaLife::CSeaLife() { // Initialize member variables m_pDolphinGroupObject = NULL; m_pDolphinObject = NULL; m_pFloorObject = NULL; m_pFish1Object = NULL; m_pd3dDevice = NULL; m_pDeviceInfo = NULL; } //----------------------------------------------------------------------------- // Name: OneTimeSceneInit() // Desc: Called during initial app startup, this function performs all the // permanent initialization. //----------------------------------------------------------------------------- HRESULT CSeaLife::OneTimeSceneInit() { HRESULT hr; m_pDolphinGroupObject = NULL; m_pDolphinObject = NULL; m_pFloorObject = NULL; m_pFish1Object = NULL; m_pd3dDevice = NULL; m_pDeviceInfo = NULL; m_pDolphinGroupObject = new CD3DFile(); m_pDolphinObject = new CD3DFile(); m_pFloorObject = new CD3DFile(); m_pFish1Object = new CD3DFile(); hr = m_pDolphinGroupObject->Load(TEXT("dolphin_group.x")); hr |= m_pDolphinGroupObject->GetMeshVertices(TEXT("Dolph01"), &m_pDolphin1Vertices, &m_dwNumDolphinVertices); hr |= m_pDolphinGroupObject->GetMeshVertices(TEXT("Dolph02"), &m_pDolphin2Vertices, &m_dwNumDolphinVertices); hr |= m_pDolphinGroupObject->GetMeshVertices(TEXT("Dolph03"), &m_pDolphin3Vertices, &m_dwNumDolphinVertices); if (FAILED(hr)) { MessageBox(NULL, TEXT("Error loading DOLPHIN_GROUP.X file"), TEXT("Dolphins"), MB_OK|MB_ICONERROR); return E_FAIL; } hr = m_pDolphinObject->Load(TEXT("dolphin.x")); hr |= m_pDolphinObject->GetMeshVertices(TEXT("Dolph02"), &m_pDolphinVertices, &m_dwNumDolphinVertices); if (FAILED(hr)) { MessageBox(NULL, TEXT("Error loading DOLPHIN.X file"), TEXT("Dolphins"), MB_OK|MB_ICONERROR); return E_FAIL; } hr = m_pFloorObject->Load(TEXT("seafloor.x")); hr |= m_pFloorObject->GetMeshVertices(TEXT("SeaFloor"), &m_pFloorVertices, &m_dwNumFloorVertices); if (FAILED(hr)) { MessageBox(NULL, TEXT("Error loading SEAFLOOR.X file"), TEXT("Dolphins"), MB_OK|MB_ICONERROR); return E_FAIL; } hr = m_pFish1Object->Load(TEXT("clownfish2.x")); D3DTextr_CreateTextureFromFile(TEXT("seafloor.bmp")); D3DTextr_CreateTextureFromFile(TEXT("dolphin.bmp")); srand(5); // Scale the sea floor vertices, and add some bumpiness for(DWORD i=0; i NUM_DOLPHINS)) { m_FishState[i].type=FISHTYPE_FISH1; m_FishState[i].pitchchange= (float)PITCHCHANGEFISH; m_FishState[i].pitchdelta= PITCHDELTAFISH; m_FishState[i].turndelta=(float)TURNDELTAFISH; m_FishState[i].angle_tweak =TWEAKFISH; m_FishState[i].speed = FISHSPEED; ; } } m_FishState[0].type=FISHTYPE_CAMERA; m_FishState[0].turndelta=(float)TURNDELTADOLPHIN; m_FishState[0].angle_tweak =TWEAK; srand (time (0)); return S_OK; } //----------------------------------------------------------------------------- // Name: FinalCleanup() // Desc: Called before the app exits, this function gives the app the chance // to cleanup after itself. //----------------------------------------------------------------------------- HRESULT CSeaLife::FinalCleanup() { SAFE_DELETE(m_pDolphinGroupObject); SAFE_DELETE(m_pDolphinObject); SAFE_DELETE(m_pFloorObject); //dont cleanup device object.. D3DTextr_InvalidateAllTextures(); return S_OK; } //----------------------------------------------------------------------------- // Name: BlendMeshes() // Desc: Does a linear interpolation between all vertex positions and normals // in two source meshes and outputs the result to the destination mesh. // This function assumes that all strided vertices have the same stride, // and that each mesh contains the same number of vertices //----------------------------------------------------------------------------- VOID BlendMeshes(D3DVERTEX* pDstMesh, D3DVERTEX* pSrcMesh1, D3DVERTEX* pSrcMesh2, DWORD dwNumVertices, FLOAT fWeight) { FLOAT fInvWeight = 1.0f - fWeight; // LERP positions and normals for(DWORD i=0; ix = fWeight*pSrcMesh1->x + fInvWeight*pSrcMesh2->x; pDstMesh->y = fWeight*pSrcMesh1->y + fInvWeight*pSrcMesh2->y; pDstMesh->z = fWeight*pSrcMesh1->z + fInvWeight*pSrcMesh2->z; pDstMesh->nx = fWeight*pSrcMesh1->nx + fInvWeight*pSrcMesh2->nx; pDstMesh->ny = fWeight*pSrcMesh1->ny + fInvWeight*pSrcMesh2->ny; pDstMesh->nz = fWeight*pSrcMesh1->nz + fInvWeight*pSrcMesh2->nz; pDstMesh++; pSrcMesh1++; pSrcMesh2++; } } //----------------------------------------------------------------------------- // Name: Render() // Desc: Called once per frame, the call is the entry point for 3d // rendering. This function sets up render states, clears the // viewport, and renders the scene. //----------------------------------------------------------------------------- HRESULT CSeaLife::Render(LPDIRECT3DDEVICE7 lpDev) { float fWeight; D3DMATRIX* pmatDest=NULL; D3DUtil_SetIdentityMatrix(m_matFloor); if (lpDev!=m_pd3dDevice) { D3DTextr_RestoreAllTextures(lpDev); } m_pd3dDevice=lpDev; // Clear the viewport m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, WATER_COLOR, 1.0f, 0L); // Begin the scene if (SUCCEEDED(m_pd3dDevice->BeginScene())) { m_pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &m_matFloor); m_pFloorObject->Render(m_pd3dDevice); // Move the dolphin in a circle CD3DFileObject* pDolphinObject = m_pDolphinObject->FindObject(TEXT("x3ds_Dolph02")); CD3DFileObject* pFish1Object = m_pFish1Object->FindObject(TEXT("clownfish_root")); for (int i =0;iSetTransform(D3DTRANSFORMSTATE_WORLD, &m_matFloor); pmatDest = pDolphinObject->GetMatrix(); *pmatDest=m_FishState[i].matrix; m_pDolphinObject->Render(m_pd3dDevice); } break; case FISHTYPE_FISH1: if (pFish1Object) { m_pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &m_matFloor); pmatDest = pFish1Object->GetMatrix(); *pmatDest=m_FishState[i].matrix; m_pFish1Object->Render(m_pd3dDevice); } break; } } // End the scene. m_pd3dDevice->EndScene(); } return S_OK; } //----------------------------------------------------------------------------- // Name: InitDeviceObjects() // Desc: Initialize scene objects. //----------------------------------------------------------------------------- HRESULT CSeaLife::InitDeviceObjects(LPDIRECT3DDEVICE7 pDev ,D3DEnum_DeviceInfo* pInfo) { if (!pDev) return E_FAIL; m_pd3dDevice=pDev; m_pDeviceInfo=pInfo; // Set up the lighting states // if (m_pDeviceInfo->ddDeviceDesc.dwVertexProcessingCaps & // D3DVTXPCAPS_DIRECTIONALLIGHTS) { D3DLIGHT7 light; D3DUtil_InitLight(light, D3DLIGHT_DIRECTIONAL, 0.0f, -1.0f, 0.0f); m_pd3dDevice->SetLight(0, &light); m_pd3dDevice->LightEnable(0, TRUE); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, TRUE); } m_pd3dDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x33333333); // Set the transform matrices D3DVIEWPORT7 vp; m_pd3dDevice->GetViewport(&vp); FLOAT fAspect = ((FLOAT)vp.dwHeight) / vp.dwWidth; D3DVECTOR vEyePt = D3DVECTOR(0.0f, 0.0f, -10.0f); D3DVECTOR vLookatPt = D3DVECTOR(0.0f, 0.0f, 0.0f); D3DVECTOR vUpVec = D3DVECTOR(0.0f, 1.0f, 0.0f); D3DMATRIX matWorld, matProj; D3DUtil_SetIdentityMatrix(matWorld); m_pd3dDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &matWorld); D3DMATRIX matView; D3DUtil_SetViewMatrix(matView,vEyePt, vLookatPt, vUpVec); m_pd3dDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &matView); D3DUtil_SetProjectionMatrix(matProj, g_PI/3, fAspect, 1.0f, 1000.0f); m_pd3dDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj); // Set up textures D3DTextr_RestoreAllTextures(m_pd3dDevice); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR); m_pd3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR); // Set default render states m_pd3dDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, TRUE); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE); // Turn on fog FLOAT fFogStart = 1.0f; FLOAT fFogEnd = 50.0f; FLOAT fDense = 0.5f; //note turn off fog for RGB //m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, TRUE); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, WATER_COLOR); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGDENSITY, *(DWORD*)(&fDense)); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, *((DWORD *)(&fFogStart))); m_pd3dDevice->SetRenderState(D3DRENDERSTATE_FOGEND, *((DWORD *)(&fFogEnd))); D3DTextr_Restore(TEXT("seafloor.bmp") ,m_pd3dDevice); D3DTextr_Restore(TEXT("dolphin.bmp"), m_pd3dDevice); return S_OK; } //----------------------------------------------------------------------------- // Name: DeleteDeviceObjects() // Desc: Called when the app is exitting, or the device is being changed, // this function deletes any device dependant objects. //----------------------------------------------------------------------------- HRESULT CSeaLife::DeleteDeviceObjects() { D3DTextr_InvalidateAllTextures(); return S_OK; } //----------------------------------------------------------------------------- // Name: FrameMove() // Desc: Called once per frame, the call is the entry point for animating // the scene. //----------------------------------------------------------------------------- HRESULT CSeaLife::FrameMove(FLOAT fTimeKeyIn) { D3DVECTOR vDirXZ; D3DVECTOR vDeltaXZ; float dotProd; static DWORD dwLastTime=0; float deltaspeed=.002f; DWORD dwThisTime=timeGetTime(); if (dwLastTime != 0) { deltaspeed=((float)(dwThisTime-dwLastTime))/10000.0f; } dwLastTime=dwThisTime; float fT,fT2,fT3 ; D3DMATRIX matFish; D3DMATRIX matYRotate,matZRotate,matXRotate; D3DMATRIX matTrans1, matScale; D3DMATRIX matRotate1, matRotate2; D3DMATRIX matTemp,matTemp2; FLOAT fPhase; FLOAT fKickFreq; FLOAT fTimeKey; FLOAT fJiggleFreq; for (int i=0; i< NUM_FISH;i++) { //time based numbers fTimeKey=fTimeKeyIn+i*2; fKickFreq = 3*fTimeKey; fJiggleFreq = fTimeKey; fT=-(DOLPHINUPDOWN(fKickFreq)); fT2=-fT/2; fT3=(float) ((3.1415/32)*sin(fTimeKeyIn/10)); fPhase = (fTimeKey)/3; m_FishState[i].weight= - (float)sin(fKickFreq); //get the vector from current location to the goal vDeltaXZ=m_FishState[i].goal -m_FishState[i].loc ; vDeltaXZ.y=0; //transpose x and z coordinates to find normal to direction //only for the dolphin though vDirXZ.x =-m_FishState[i].dir.z; vDirXZ.z = m_FishState[i].dir.x; vDirXZ.y =0; //take dot product to determine what side to turn to dotProd=DotProduct(vDeltaXZ,vDirXZ); // turn by adding yaw if (dotProd < -m_FishState[i].turndelta) m_FishState[i].yaw +=m_FishState[i].angle_tweak; if (dotProd > m_FishState[i].turndelta) m_FishState[i].yaw -=m_FishState[i].angle_tweak; // now see how far we have to go up and down. float deltaY=m_FishState[i].goal.y - m_FishState[i].loc.y; if (deltaY < -m_FishState[i].pitchdelta) { m_FishState[i].pitch+=m_FishState[i].pitchchange; if (m_FishState[i].pitch > 0.8f) m_FishState[i].pitch=0.8f; } else if (deltaY > PITCHDELTA) { m_FishState[i].pitch-=m_FishState[i].pitchchange; if (m_FishState[i].pitch < -0.8f) m_FishState[i].pitch=-0.8f; } else { m_FishState[i].pitch *= .95f; } if (m_FishState[i].type==FISHTYPE_FISH1) { //note for the dolphin we will modulate the pitch D3DUtil_SetRotateYMatrix(matYRotate, (float) (m_FishState[i].yaw+FISHWIGGLE)); D3DUtil_SetRotateXMatrix(matXRotate,-m_FishState[i].pitch); D3DMath_MatrixMultiply(matTemp, matXRotate, matYRotate); //ak } else if (m_FishState[i].type==FISHTYPE_CAMERA) { D3DUtil_SetRotateYMatrix(matYRotate,m_FishState[i].yaw); D3DUtil_SetRotateXMatrix(matXRotate,-m_FishState[i].pitch); D3DMath_MatrixMultiply(matTemp, matXRotate, matYRotate); //ak } else { //note for the dolphin we will modulate the pitch D3DUtil_SetRotateYMatrix(matYRotate,m_FishState[i].yaw); D3DUtil_SetRotateXMatrix(matXRotate,-m_FishState[i].pitch+fT); D3DMath_MatrixMultiply(matTemp, matXRotate, matYRotate); //ak } //extract a new direction vector m_FishState[i].dir[0] = -matTemp(2, 0); m_FishState[i].dir[1] = -matTemp(2, 1); m_FishState[i].dir[2] = -matTemp(2, 2); //normalize direction m_FishState[i].dir = Normalize(m_FishState[i].dir); if (m_FishState[i].type ==FISHTYPE_CAMERA) { D3DVECTOR local_up; D3DVECTOR from; D3DVECTOR at; D3DVECTOR loc = m_FishState[i].loc; D3DVECTOR dir = m_FishState[i].dir; D3DMATRIX view; local_up.x =matTemp(1, 0); local_up.y =matTemp(1, 1); local_up.z =matTemp(1, 2); from=loc; // - 20 * dir + 3* local_up; at= loc+dir; //SetViewParams(&from,&at,&local_up,1.0f); } //update the location //TODO make time based m_FishState[i].loc += m_FishState[i].speed *deltaspeed* m_FishState[i].dir; //if we near our goal choose another one D3DVECTOR vRes = (m_FishState[i].goal - m_FishState[i].loc); if ((((int)abs(vRes.x)) < 1) && (((int)abs(vRes.z)) < 1)) { m_FishState[i].goal=D3DVECTOR(XEXTENT,YEXTENT,ZEXTENT); } if (m_FishState[i].type==FISHTYPE_FISH1) { D3DUtil_SetRotateXMatrix(matRotate2,-m_FishState[i].pitch); D3DUtil_SetScaleMatrix(matScale,10,10,10); D3DUtil_SetRotateYMatrix(matRotate1,m_FishState[i].yaw+FISHWIGGLE); if (rnd()<.01) { m_FishState[i].goal=D3DVECTOR(XEXTENT,YEXTENT,ZEXTENT); } } else if (m_FishState[i].type==FISHTYPE_CAMERA) { D3DUtil_SetRotateXMatrix(matRotate2,-m_FishState[i].pitch); D3DUtil_SetScaleMatrix(matScale,10,10,10); D3DUtil_SetRotateYMatrix(matRotate1,m_FishState[i].yaw); if (rnd()<.01) { m_FishState[i].goal=D3DVECTOR(XEXTENT,YEXTENT,ZEXTENT); } } else { D3DUtil_SetScaleMatrix(matScale,1,1,1); D3DUtil_SetRotateZMatrix(matRotate2,m_FishState[i].pitch +fT2); D3DUtil_SetRotateYMatrix(matRotate1,m_FishState[i].yaw-3.1415/2); } D3DUtil_SetTranslateMatrix(matTrans1, m_FishState[i].loc.x, m_FishState[i].loc.y, m_FishState[i].loc.z); D3DMath_MatrixMultiply(matTemp, matRotate2, matRotate1); D3DMath_MatrixMultiply(matTemp2, matTemp, matScale); D3DMath_MatrixMultiply(matFish, matTemp2, matTrans1); m_FishState[i].matrix = matFish; } return S_OK; } #if 0 float dot = DotProduct (offset, FISH[i].delta); offset = CrossProduct (offset, FISH[i].delta); dot = (1.0f-dot)/2.0f * angle_tweak * 10.0f; if (offset.y > 0.01) { FISH[i].dyaw = (FISH[i].dyaw*9.0f + dot) * 0.1f; } else if (offset.y < 0.01) { FISH[i].dyaw = (FISH[i].dyaw*9.0f - dot) * 0.1f; } FISH[i].yaw += FISH[i].dyaw; FISH[i].roll = -FISH[i].dyaw * 9.0f; #endif