예제 #1
0
NzVector3f DampedString(const NzVector3f& currentPos, const NzVector3f& targetPos, float frametime, float springStrength)
{
	// Je ne suis pas l'auteur de cette fonction
	// Je l'ai reprise du programme "Floaty Camera Example" et adaptée au C++
	// Trouvé ici: http://nccastaff.bournemouth.ac.uk/jmacey/RobTheBloke/www/opengl_programming.html#4
	// Tout le mérite revient à l'auteur (Qui me permettra ainsi d'améliorer les démos, voire même le moteur)

	// calculate the displacement between the target and the current position
	NzVector3f displacement = targetPos - currentPos;

	// whats the distance between them?
	float displacementLength = displacement.GetLength();

	// Stops small position fluctuations (integration errors probably - since only using euler)
	if (NzNumberEquals(displacementLength, 0.f))
		return currentPos;

	float invDisplacementLength = 1.f/displacementLength;

	const float dampConstant = 0.000065f; // Something v.small to offset 1/ displacement length

	// the strength of the spring increases the further away the camera is from the target.
	float springMagitude = springStrength*displacementLength + dampConstant*invDisplacementLength;

	// Normalise the displacement and scale by the spring magnitude
	// and the amount of time passed
	float scalar = std::min(invDisplacementLength * springMagitude * frametime, 1.f);
	displacement *= scalar;

	// move the camera a bit towards the target
	return currentPos + displacement;
}
예제 #2
0
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;
        }
}
예제 #3
0
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;
    }

}
예제 #4
0
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());
}
예제 #5
0
unsigned int NzLightManager::ComputeClosestLights(const NzVector3f& position, float squaredRadius, unsigned int maxResults)
{
	m_results.resize(maxResults);
	for (Light& light : m_results)
	{
		light.light = nullptr;
		light.score = std::numeric_limits<unsigned int>::max(); // Nous jouons au Golf
	}

	for (unsigned int i = 0; i < m_lights.size(); ++i)
	{
		const NzLight** lights = m_lights[i].first;
		unsigned int lightCount = m_lights[i].second;

		for (unsigned int j = 0; j < lightCount; ++j)
		{
			const NzLight* light = *lights++;

			unsigned int score = std::numeric_limits<unsigned int>::max();
			switch (light->GetLightType())
			{
				case nzLightType_Directional:
					score = 0; // Lumière choisie d'office
					break;

				case nzLightType_Point:
				{
					float lightRadius = light->GetRadius();

					float squaredDistance = position.SquaredDistance(light->GetPosition());
					if (squaredDistance - squaredRadius <= lightRadius*lightRadius)
						score = static_cast<unsigned int>(squaredDistance*1000.f);

					break;
				}

				case nzLightType_Spot:
				{
					float lightRadius = light->GetRadius();

					///TODO: Attribuer bonus/malus selon l'angle du spot ?
					float squaredDistance = position.SquaredDistance(light->GetPosition());
					if (squaredDistance - squaredRadius <= lightRadius*lightRadius)
						score = static_cast<unsigned int>(squaredDistance*1000.f);

					break;
				}
			}

			if (score < m_results[0].score)
			{
				unsigned int k;
				for (k = 1; k < maxResults; ++k)
				{
					if (score > m_results[k].score)
						break;
				}

				k--; // Position de la nouvelle lumière

				// Décalage
				std::memcpy(&m_results[0], &m_results[1], k*sizeof(Light));

				m_results[k].light = light;
				m_results[k].score = score;
			}
		}
	}

	unsigned int i;
	for (i = 0; i < maxResults; ++i)
	{
		if (m_results[i].light)
			break;
	}

	return maxResults-i;
}