|
|
//-----------------------------------------------------------------------------
// 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 <ddraw.h>
#include <d3d.h>
#include "D3DApp.h"
#include "D3DUtil.h"
#include "D3DMath.h"
#include "D3DTextr.h"
#include "D3DFile.h"
#include <math.h>
#include <time.h>
//#include <mmsystem.h>
#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<m_dwNumFloorVertices; i++) { m_pFloorVertices[i].y += (rand()/(FLOAT)RAND_MAX); m_pFloorVertices[i].y += (rand()/(FLOAT)RAND_MAX); m_pFloorVertices[i].y += (rand()/(FLOAT)RAND_MAX); m_pFloorVertices[i].tu *= 10; m_pFloorVertices[i].tv *= 10; }
// Scale the dolphin vertices (the model file is too big)
for(i=0; i<m_dwNumDolphinVertices; i++) { D3DVECTOR vScale(0.01f, 0.01f, 0.01f); *((D3DVECTOR*)(&m_pDolphin1Vertices[i])) *= vScale; *((D3DVECTOR*)(&m_pDolphin2Vertices[i])) *= vScale; *((D3DVECTOR*)(&m_pDolphin3Vertices[i])) *= vScale; }
for (i=0; i<NUM_FISH;i++) { ZeroMemory(&m_FishState[i],sizeof(FISHSTRUCT)); m_FishState[i].type=FISHTYPE_DOLPHIN; m_FishState[i].dir=D3DVECTOR(0,0,1); m_FishState[i].goal=D3DVECTOR(XEXTENT,YEXTENT,ZEXTENT); m_FishState[i].loc=D3DVECTOR(XEXTENT,0,ZEXTENT); m_FishState[i].speed = DOLPHINSPEED; m_FishState[i].angle_tweak =TWEAK; m_FishState[i].pitch=INITPITCH; m_FishState[i].turndelta=(float)TURNDELTADOLPHIN; m_FishState[i].pitchchange= (float)PITCHCHANGE; m_FishState[i].pitchdelta= PITCHDELTA;
if ((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; i<dwNumVertices; i++) { pDstMesh->x = 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;i<NUM_FISH;i++) { switch (m_FishState[i].type) { case FISHTYPE_DOLPHIN:
fWeight=-m_FishState[i].weight;
if(fWeight < 0.0f) { BlendMeshes(m_pDolphinVertices, m_pDolphin3Vertices, m_pDolphin2Vertices, m_dwNumDolphinVertices, -fWeight); } else { BlendMeshes(m_pDolphinVertices, m_pDolphin1Vertices, m_pDolphin2Vertices, m_dwNumDolphinVertices, fWeight); }
if (pDolphinObject) { m_pd3dDevice->SetTransform(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
|