NzVector3f NzTerrainQuadTree::GetVertexPosition(const NzTerrainNodeID& nodeID, int x, int y) { ///Les terrains sont centrées en 0 ///Avec le système de node ///Leur position "affichée" peut changer à l'exécution ///La configuration ne peut donc pas contenir la position du terrain, ce doit être géré par lee système de node ///Néanmoins, pour un terrain infini, les quadtree autres que le central doivent avoir un offset ///Par conséquent la configuration contient la taille du terrain en floattant ///Et un offset (x,y) en coordonnées entières //Note : nodeID.depth should never be < 0 float power = 1.f/(1 << nodeID.depth); NzVector3f position; switch(m_type) { case nzQuadTreeType_terrain: position.x = m_terrainConfiguration.terrainSize * (m_commonConfiguration.x_offset + (x * 0.25f + nodeID.locx) * power); position.z = m_terrainConfiguration.terrainSize * (m_commonConfiguration.y_offset + (y * 0.25f + nodeID.locy) * power); position.y = m_heightSource2D->GetHeight(position.x,position.z) * m_commonConfiguration.maxHeight; return m_rotationMatrix.Transform(position); break; case nzQuadTreeType_planet: default: //Les coordonnées d'un plan position.x = 2.f * (x * 0.25f + nodeID.locx) / std::pow(2,nodeID.depth) - 1.f; position.y = 1.f; position.z = 2.f * (y * 0.25f + nodeID.locy) / std::pow(2,nodeID.depth) - 1.f; //On normalise le vecteur pour obtenir une sphère position.Normalize(); position *= m_planetConfiguration.planetRadius; //On l'oriente correctement position = m_rotationMatrix.Transform(position); //Et applique la hauteur en cette position (A Optimiser) float height = m_heightSource3D->GetHeight(position.x, position.y, position.z) * m_commonConfiguration.maxHeight; position.Normalize(); position *= m_planetConfiguration.planetRadius + height; ///position += m_commonConfiguration.center; return position; break; } }
void NzPatch::ComputeNormals() { //top, right, bottom, left NzVector3f v1,v2,v3,v4; NzVector3f v12; NzVector3f v23; NzVector3f v34; NzVector3f v41; NzVector3f sum; unsigned int i0,j0; unsigned int hx,hy; NzVector2i normalLocation; for(unsigned int j(0) ; j < 5 ; ++j) for(unsigned int i(0) ; i < 5 ; ++i) { i0 = i + 1; j0 = j + 1; normalLocation.x = (m_id.locx * 4 + i) * std::pow(2,NAZARA_DYNATERRAIN_MAXIMUM_TERRAIN_DEPTH - m_id.depth); normalLocation.y = (m_id.locy * 4 + j) * std::pow(2,NAZARA_DYNATERRAIN_MAXIMUM_TERRAIN_DEPTH - m_id.depth); if(m_data->normalsManager->IsNormalSet(normalLocation)) { m_data->normalsManager->GetNormal(normalLocation,sum); } else { //Compute four vectors v1 = m_vertices[i0+1][j0 ].GetPosition(); v2 = m_vertices[i0 ][j0+1].GetPosition(); v3 = m_vertices[i0-1][j0 ].GetPosition(); v4 = m_vertices[i0+1][j0-1].GetPosition(); v12 = v1.CrossProduct(v2); v23 = v2.CrossProduct(v3); v34 = v3.CrossProduct(v4); v41 = v4.CrossProduct(v1); sum = v12 + v23 + v34 + v41; sum.Normalize(); if(sum.y < 0.f) sum *= -1.f; m_data->normalsManager->SetNormal(normalLocation,sum,this); } m_data->normalsManager->AddNormalListenner(normalLocation,this); m_vertexNormals.at(i+5*j) = sum; } }
void NzSubMesh::GenerateTangents() { NzTriangleIterator iterator(this); do { NzVector3f pos0 = iterator.GetPosition(0); NzVector2f uv0 = iterator.GetTexCoord(0); NzVector3f dv[2]; dv[0] = iterator.GetPosition(1) - pos0; dv[1] = iterator.GetPosition(2) - pos0; NzVector2f duv[2]; duv[0] = iterator.GetTexCoord(1) - uv0; duv[1] = iterator.GetTexCoord(2) - uv0; float ds[2]; ds[0] = iterator.GetTexCoord(1).x - uv0.x; ds[1] = iterator.GetTexCoord(2).x - uv0.x; NzVector3f ppt; ppt.x = ds[0]*dv[1].x - dv[0].x*ds[1]; ppt.y = ds[0]*dv[1].y - dv[0].y*ds[1]; ppt.z = ds[0]*dv[1].z - dv[0].z*ds[1]; ppt.Normalize(); for (unsigned int i = 0; i < 3; ++i) { NzVector3f normal = iterator.GetNormal(i); float d = ppt.DotProduct(normal); NzVector3f tangent = ppt - (d * normal); iterator.SetTangent(i, tangent); } } while (iterator.Advance()); }