//------------------------------------------------------------------------ void FlyMatrix::LookAt(FlyVector vcPos, FlyVector vcLookAt,FlyVector vcWorldUp) { FlyVector vcDir = vcLookAt - vcPos; FlyVector vcUp, vcRight; float fAngle=0.0f; vcDir.Normalize(); fAngle = vcWorldUp * vcDir; vcUp = vcWorldUp - (vcDir * fAngle); vcUp.Normalize(); vcRight.Cross(vcUp, vcDir); _11 = vcRight.x; _21 = vcUp.x; _31 = vcDir.x; _12 = vcRight.y; _22 = vcUp.y; _32 = vcDir.y; _13 = vcRight.z; _23 = vcUp.z; _33 = vcDir.z; _41 = vcPos.x; _42 = vcPos.y; _43 = vcPos.z; _14=0.0f; _24=0.0f; _34=0.0f; _44=1.0f; }
//------------------------------------------------------------------------ // Initialize the terrain tile. // ---------------------------------------------------------------------- // Param -> IN: // int,int: Position where we start to read the height data. // const float*: Pointer to the height data. //------------------------------------------------------------------------ HRESULT etTile::Initialize( int startx,int startz,const float* pHeightData ) { m_nStartX = startx; m_nStartZ = startz; // Get the resourceManager. FlyResourceManager* pResMgr = etCoreManager::Instance().GetResourceManager(); // Create the shared vertex buffer. UINT nTileSize = m_pLevel->GetTileSize(); m_pVB = pResMgr->MakeVertexBuffer( (nTileSize+1)*(nTileSize+1)*sizeof(VERTEX2T), BU_WRITEONLY,MM_MANAGED ); if( !m_pVB ) return FLY_CREATEBUFFER; float fMinHeight = 0.0f; float fMaxHeight = 0.0f; int endx = startx + nTileSize + 1; int endz = startz + nTileSize + 1; VERTEX2T* pVerts = (VERTEX2T*)m_pVB->Lock( 0,(nTileSize+1)*(nTileSize+1)*sizeof(VERTEX2T),LOCK_NORMAL ); for( int j=startz;j<endz;j++ ) { for( int i=startx;i<endx;i++ ) { float fHeight = pHeightData[j*(m_pLevel->GetTerrainSize()+1)+i]; fHeight *= m_pLevel->GetHeightScale(); pVerts->x = (float)i * m_pLevel->GetLengthPerUnit(); pVerts->y = fHeight; pVerts->z = (float)j * m_pLevel->GetLengthPerUnit(); pVerts->vN[0] = 0.0f; pVerts->vN[1] = 1.0f; pVerts->vN[2] = 0.0f; pVerts->tu0 = ((float)i / (float)nTileSize); pVerts->tv0 = ((float)j / (float)nTileSize); pVerts->tu1 = ((float)i / (float)m_pLevel->GetTerrainSize()); pVerts->tv1 = ((float)j / (float)m_pLevel->GetTerrainSize()); pVerts++; if( fHeight < fMinHeight ) fMinHeight = fHeight; if( fHeight > fMaxHeight ) fMaxHeight = fHeight; } } m_pVB->Unlock(); // Set the boundingBox. m_Bounds.vcMin.x = (float)startx * m_pLevel->GetLengthPerUnit(); m_Bounds.vcMin.y = fMinHeight - 1.0f; m_Bounds.vcMin.z = (float)startz * m_pLevel->GetLengthPerUnit(); m_Bounds.vcMax.x = (float)(endx-1) * m_pLevel->GetLengthPerUnit(); m_Bounds.vcMax.y = fMaxHeight + 1.0f; m_Bounds.vcMax.z = (float)(endz-1) * m_pLevel->GetLengthPerUnit(); // Set the boundingRect. m_BRect.SetMinPoint( m_Bounds.vcMin.x,m_Bounds.vcMin.z ); m_BRect.SetMaxPoint( m_Bounds.vcMax.x,m_Bounds.vcMax.z ); // Create the renderable object for the tile. m_pRenderable = new etTileRenderable( this ); m_pRenderable->m_BBox = m_Bounds; m_pRenderable->m_pVB = m_pVB; m_pRenderable->m_nNumVerts = (nTileSize+1)*(nTileSize+1); // Create the renderable object when tile is selected. m_pSelected = new etTileSelected( this ); m_pSelected->BuildGeometry(); FlyRenderEffect* pEffect = etCoreManager::Instance().GetTerrainFX(); m_pRenderable->m_pMaterial->AddNewTechnique( pEffect->GetTechniqueByIndex(0) ); m_pRenderable->m_pMaterial->AddNewTechnique( pEffect->GetTechniqueByIndex(1) ); m_pRenderable->m_pMaterial->AddNewTechnique( pEffect->GetTechniqueByIndex(2) ); m_pRenderable->m_pMaterial->AddNewTechnique( pEffect->GetTechniqueByIndex(3) ); m_pRenderable->m_pMaterial->SetActiveTechnique( 0 ); // Initialize the default GPU parameters. FlyRenderEffectInstance* pGPUProgram; FlyVector vLightDir = m_pManager->GetLightDirection(); vLightDir.Normalize(); for( int i=0;i<4;i++ ) { pGPUProgram = m_pRenderable->m_pMaterial->GetRenderEffectInstance(i); *pGPUProgram->GetParameterByIndex(0) = m_pMainTexture; *pGPUProgram->GetParameterByIndex(1) = m_pLevel->GetDetailLayer()->GetTexture(); *pGPUProgram->GetParameterByIndex(2) = m_pDetails[0]; *pGPUProgram->GetParameterByIndex(3) = m_pDetails[1]; *pGPUProgram->GetParameterByIndex(4) = m_pDetails[2]; *pGPUProgram->GetParameterByIndex(5) = m_pDetails[3]; *pGPUProgram->GetParameterByIndex(6) = m_fMainScale; *pGPUProgram->GetParameterByIndex(7) = m_fDetailScale[0]; *pGPUProgram->GetParameterByIndex(8) = m_fDetailScale[1]; *pGPUProgram->GetParameterByIndex(9) = m_fDetailScale[2]; *pGPUProgram->GetParameterByIndex(10) = m_fDetailScale[3]; *pGPUProgram->GetParameterByIndex(11) = m_pManager->GetLightingMode(); *pGPUProgram->GetParameterByIndex(12) = vLightDir; *pGPUProgram->GetParameterByIndex(13) = *((FlyVector*)&m_pManager->GetLightAmbient()); *pGPUProgram->GetParameterByIndex(14) = *((FlyVector*)&m_pManager->GetLightDiffuse()); *pGPUProgram->GetParameterByIndex(16) = *((FlyVector*)&m_pManager->GetWireColor()); } return FLY_OK; }
//------------------------------------------------------------------------ // Test the intersect with a segment. // ---------------------------------------------------------------------- // Param -> IN: // const FlyVector&: First point of the segment. // const FlyVector&: Second point of the segment. // FlyVector*: To store the point of intersection. //------------------------------------------------------------------------ bool etTile::IntersectSegment( const FlyVector& vStart,const FlyVector& vEnd, FlyVector* pOut ) { FlyVector vDir = vEnd - vStart; FlyVector vRay = vStart; // 1. Special case... if( vDir.x == 0 && vDir.z == 0 ) { float h = m_pLevel->GetScaledHeightValue( vRay.x,vRay.z ); if( (vStart.y <= h && vEnd.y >= h) || (vStart.y >= h && vEnd.y <= h) ) { if( pOut ) { *pOut = vRay; pOut->y = h; } return true; } else { if( pOut ) *pOut = FlyVector( -1.0f,-1.0f,-1.0f ); return false; } } vDir.Normalize(); vRay += vDir; float h = m_pLevel->GetScaledHeightValue( vRay.x,vRay.z ); while( vRay.x >= m_Bounds.vcMin.x && vRay.x <= m_Bounds.vcMax.x && vRay.z >= m_Bounds.vcMin.z && vRay.z <= m_Bounds.vcMax.z ) { if( vRay.y <= h ) { if( pOut ) *pOut = vRay; return true; } else { vRay += vDir; } if( vRay.y - vEnd.y < 1.0f ) break; } if( vRay.x < m_Bounds.vcMin.x && m_pNeighbors[NB_WEST] != NULL ) return m_pNeighbors[NB_WEST]->IntersectSegment( vRay,vEnd,pOut ); else if( vRay.z < m_Bounds.vcMin.z && m_pNeighbors[NB_SOUTH] != NULL ) return m_pNeighbors[NB_SOUTH]->IntersectSegment( vRay,vEnd,pOut ); else if( vRay.x > m_Bounds.vcMax.x && m_pNeighbors[NB_EAST] != NULL ) return m_pNeighbors[NB_EAST]->IntersectSegment( vRay,vEnd,pOut ); else if( vRay.z > m_Bounds.vcMax.z && m_pNeighbors[NB_NORTH] != NULL ) return m_pNeighbors[NB_NORTH]->IntersectSegment( vRay,vEnd,pOut ); else { if( pOut ) *pOut = FlyVector( -1.0f,-1.0f,-1.0f ); return false; } }