//------------------------------------------------------------------------ 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; }
//------------------------------------------------------------------------ // Notify the camera's state, Decide the lod of this tile. // ---------------------------------------------------------------------- // Param -> IN: // FlyCameraBase*: Pointer to the current camera. //------------------------------------------------------------------------ void etTile::NotifyCamera( FlyCameraBase* pCamera ) { FlySceneObject::NotifyCamera( pCamera ); FlyVector vDiff = pCamera->GetPosition()-m_WorldBBox.GetCenter(); float fL = vDiff.GetSqrLength(); m_nLodLevel = -1; for( int i=0;i<m_pLevel->GetMaxLodLevel();i++ ) { if( m_pLevel->GetLodSqrDist(i) > fL ) { m_nLodLevel = i - 1; break; } } if( m_nLodLevel < 0 ) m_nLodLevel = m_pLevel->GetMaxLodLevel() - 1; }
//------------------------------------------------------------------------ // 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; } }
//------------------------------------------------------------------------ // Transform the vertices with the bone's matrix. //------------------------------------------------------------------------ HRESULT FlyAnimation::AnimationVertices(void) { bool bChanged = false; AVERTEX* pVertex; sVertexOrig* pVertex_Orig; FlyMatrix matA,matB; FlyVector sVectorA,sVectorB; FlyVector vFinal; // Get the current animation node. sAnimNode* pCurNode = &m_AnimGroup[m_nAnimID]; FlyVector vBoxMin = FlyVector( 999999.0f, 999999.0f, 999999.0f ); FlyVector vBoxMax = FlyVector( -999999.0f,-999999.0f,-999999.0f ); for( UINT i=0;i<m_sHeader.nNumVerts;i++ ) { pVertex = &m_pVertices[i]; pVertex_Orig = &m_pVertices_Orig[i]; vFinal.Set( 0.0f,0.0f,0.0f ); // The first bone's effect. if( pVertex->fBone1 != (float)NULL_BONEID ) { matA = pCurNode->pJoints[(UINT)pVertex->fBone1].mMatrix_Absolute; sVectorA.x = pVertex_Orig->fXYZ[0]; sVectorA.y = pVertex_Orig->fXYZ[1]; sVectorA.z = pVertex_Orig->fXYZ[2]; sVectorA.RotateWith( matA ); sVectorA += matA.GetTranslation(); bChanged = true; } // The second bone's effect. if( pVertex->fBone2 != (float)NULL_BONEID ) { matB = pCurNode->pJoints[(UINT)pVertex->fBone2].mMatrix_Absolute; sVectorB.x = pVertex_Orig->fXYZ[0]; sVectorB.y = pVertex_Orig->fXYZ[1]; sVectorB.z = pVertex_Orig->fXYZ[2]; sVectorB.RotateWith( matB ); sVectorB += matB.GetTranslation(); bChanged = true; } // Blend the final position. vFinal = sVectorA*pVertex->fWeight1 + sVectorB*pVertex->fWeight2; if( bChanged ) { pVertex->x = vFinal.x; pVertex->y = vFinal.y; pVertex->z = vFinal.z; } // pVertex->x = pVertex_Orig->fXYZ[0]; // pVertex->y = pVertex_Orig->fXYZ[1]; // pVertex->z = pVertex_Orig->fXYZ[2]; // Calculate the boundingBox. if( pVertex->x < vBoxMin.x ) vBoxMin.x = pVertex->x; if( pVertex->y < vBoxMin.y ) vBoxMin.y = pVertex->y; if( pVertex->z < vBoxMin.z ) vBoxMin.z = pVertex->z; if( pVertex->x > vBoxMax.x ) vBoxMax.x = pVertex->x; if( pVertex->y > vBoxMax.y ) vBoxMax.y = pVertex->y; if( pVertex->z > vBoxMax.z ) vBoxMax.z = pVertex->z; bChanged = false; } m_BBox.vcMin = vBoxMin; m_BBox.vcMax = vBoxMax; return FLY_OK; }