// ***************************************************************************
void	NLPACS::CZoneTessellation::build()
{
	sint	el;
	uint	i, j;

	NL3D::CLandscape	landscape;
	landscape.init();

	vector<CVector>				normals;

	vector<CVector>				vectorCheck;
	bool						useNoHmZones = true;

	{
		NL3D::CLandscape	landscapeNoHm;
		landscapeNoHm.init();

		//
		// load the 9 landscape zones
		//
		for (i=0; i<_ZoneIds.size(); ++i)
		{
			string	filename = getZoneNameById(_ZoneIds[i])+ZoneExt;
			CIFile	file(CPath::lookup(filename));
			CZone	zone;
			zone.serial(file);
			file.close();

			if (Verbose)
				nlinfo("use zone %s %d", filename.c_str(), zone.getZoneId());

			if (zone.getZoneId() != _ZoneIds[i])
			{
				nlwarning ("Zone %s ID is wrong. Abort.", filename.c_str());
				return;
			}
			landscape.addZone(zone);

			if (useNoHmZones)
			{
				string	filenameNH = getZoneNameById(_ZoneIds[i])+ZoneNHExt;
				string	loadZ = CPath::lookup(filenameNH, false, false);
				if (!loadZ.empty())
				{
					CIFile	fileNH(loadZ);
					CZone	zoneNH;
					zoneNH.serial(fileNH);
					fileNH.close();
					if (zoneNH.getZoneId() != _ZoneIds[i])
					{
						nlwarning ("Zone %s ID is wrong. Abort.", filenameNH.c_str());
						return;
					}
					landscapeNoHm.addZone(zoneNH);
				}
				else
				{
					useNoHmZones = false;
				}
			}

			_ZonePtrs.push_back(landscape.getZone(_ZoneIds[i]));
		}

		landscape.setNoiseMode(false);
		landscape.checkBinds();

		if (useNoHmZones)
		{
			landscapeNoHm.setNoiseMode(false);
			landscapeNoHm.checkBinds();
		}

		BestFittingBBox.setCenter(CVector::Null);
		BestFittingBBox.setHalfSize(CVector::Null);
		BestFittingBBoxSetuped= false;

		// Compute best fitting bbox
		for (i=0; i<_ZoneIds.size(); ++i)
		{
			if (_ZoneIds[i] == CentralZoneId)
			{
				if(_ZonePtrs[i]->getNumPatchs()>0)
				{
					BestFittingBBox = _ZonePtrs[i]->getZoneBB().getAABBox();
					BestFittingBBoxSetuped= true;
				}
			}
		}

		CAABBox	enlBBox = BestFittingBBox;
		enlBBox.setHalfSize(enlBBox.getHalfSize()+CVector(8.0f, 8.0f, 1000.0f));

		// Add neighbor patch
		for (i=0; i<_ZoneIds.size(); ++i)
		{
			if (_ZoneIds[i] == CentralZoneId)
			{
				for (j=0; (sint)j<_ZonePtrs[i]->getNumPatchs(); ++j)
				{
					landscape.excludePatchFromRefineAll(_ZoneIds[i], j, false);
					if (useNoHmZones)
						landscapeNoHm.excludePatchFromRefineAll(_ZoneIds[i], j, false);
				}
				if (Verbose)
					nlinfo(" - selected %d/%d patches for zone %d", _ZonePtrs[i]->getNumPatchs(), _ZonePtrs[i]->getNumPatchs(), _ZoneIds[i]);
			}
			else
			{
				uint	nump = 0;
				for (j=0; (sint)j<_ZonePtrs[i]->getNumPatchs(); ++j)
				{
					CAABBox	pbox = _ZonePtrs[i]->getPatch(j)->buildBBox();
					bool	inters = enlBBox.intersect(pbox);

					if (inters)
					{
						landscape.excludePatchFromRefineAll(_ZoneIds[i], j, false);
						if (useNoHmZones)
							landscapeNoHm.excludePatchFromRefineAll(_ZoneIds[i], j, false);
						++nump;
					}
					else
					{
						landscape.excludePatchFromRefineAll(_ZoneIds[i], j, true);
						if (useNoHmZones)
							landscapeNoHm.excludePatchFromRefineAll(_ZoneIds[i], j, true);
					}
				}
				if (Verbose)
					nlinfo(" - selected %d/%d patches for zone %d", nump, _ZonePtrs[i]->getNumPatchs(), _ZoneIds[i]);
			}
		}

		// tessellate the landscape, get the leaves (the tessellation faces), and convert them
		// into surf elements
		if (Verbose)
			nlinfo("Compute landscape tessellation");

		if (Verbose)
			nlinfo("   - tessellate landscape");

		if (useNoHmZones)
		{
			// Before tesselate, verify that the 2 landscape zones have at least the same binds!
			// Else there will be errors because of not the same tesselation
			checkSameLandscapeHmBinds(landscape, landscapeNoHm);
			
			// Tesselate
			landscapeNoHm.setThreshold(0.0f);
			landscapeNoHm.setTileMaxSubdivision(TessellateLevel);
			landscapeNoHm.refineAll(CVector::Null);
			landscapeNoHm.averageTesselationVertices();

			// get the faces
			vector<const CTessFace *>	leavesNoHm;
			landscapeNoHm.getTessellationLeaves(leavesNoHm);

			for (el=0; el<(sint)leavesNoHm.size(); ++el)
			{
				const CTessFace	*face = leavesNoHm[el];
				const CVector	*v[3];

				// get the vertices of the face
				v[0] = &(face->VBase->EndPos);
				v[1] = &(face->VLeft->EndPos);
				v[2] = &(face->VRight->EndPos);

				normals.push_back( ((*(v[1])-*(v[0])) ^ (*(v[2])-*(v[0]))).normed() );

				vectorCheck.push_back(*(v[0]));
				vectorCheck.push_back(*(v[1]));
				vectorCheck.push_back(*(v[2]));
			}
		}
	}

	// Build the lanscape with heightmap
	landscape.setThreshold(0.0f);
	landscape.setTileMaxSubdivision(TessellateLevel);
	landscape.refineAll(CVector::Null);
	landscape.averageTesselationVertices();

	vector<const CTessFace *>	leaves;
	landscape.getTessellationLeaves(leaves);
	if (Verbose)
	{
		if (useNoHmZones)
			nlinfo("      - used no height map zones");
		nlinfo("      - generated %d leaves", leaves.size());
	}

	// If don't use NoHm zones, build normals and vectorCheck directly from std landscape
	if (!useNoHmZones)
	{
		for (el=0; el<(sint)leaves.size(); ++el)
		{
			const CTessFace	*face = leaves[el];
			const CVector	*v[3];

			// get the vertices of the face
			v[0] = &(face->VBase->EndPos);
			v[1] = &(face->VLeft->EndPos);
			v[2] = &(face->VRight->EndPos);

			normals.push_back( ((*(v[1])-*(v[0])) ^ (*(v[2])-*(v[0]))).normed() );

			vectorCheck.push_back(*(v[0]));
			vectorCheck.push_back(*(v[1]));
			vectorCheck.push_back(*(v[2]));
		}
	}

	// check that there is the same number of faces from landscape with and without heightmap
	if (normals.size() != leaves.size())
	{
		nlwarning ("ERROR : The heightmaped landscape has not the same number of polygon than the nonheightmaped landscape: %d/%d.", 
			normals.size(), leaves.size());
		exit (0);
	}

	// generate a vector of vertices and of surf element
	CHashMap<const CVector *, uint32, CHashPtr<const CVector> >				vremap;
	CHashMap<const CVector *, uint32, CHashPtr<const CVector> >::iterator	vremapit;
	CHashMap<const CTessFace *, CSurfElement *, CHashPtr<const CTessFace> >	fremap;
	CHashMap<const CTessFace *, CSurfElement *, CHashPtr<const CTessFace> >::iterator	fremapit;
	_Vertices.clear();
	_Tessellation.resize(leaves.size());

	if (Verbose)
		nlinfo("   - make and remap surface elements");

	for (el=0; el<(sint)leaves.size(); ++el)
		fremap[leaves[el]] = &(_Tessellation[el]);

	uint	check = 0;

	float	dist, maxdist = 0.0f;

	for (el=0; el<(sint)leaves.size(); ++el)
	{
		const CTessFace	*face = leaves[el];
		const CVector	*v[3];

		CSurfElement	&element = _Tessellation[el];

		// setup zone id
		element.ZoneId = face->Patch->getZone()->getZoneId();

		// get the vertices of the face
		v[0] = &(face->VBase->EndPos);
		v[1] = &(face->VLeft->EndPos);
		v[2] = &(face->VRight->EndPos);

		{
			CVector	vcheck;

			vcheck = vectorCheck[check++] - *(v[0]);
			vcheck.z = 0;
			dist = vcheck.norm();
			if (dist > maxdist)	maxdist = dist;
			//nlassert(vcheck.norm() < 0.1f);

			vcheck = vectorCheck[check++] - *(v[1]);
			vcheck.z = 0;
			dist = vcheck.norm();
			if (dist > maxdist)	maxdist = dist;
			//nlassert(vcheck.norm() < 0.1f);

			vcheck = vectorCheck[check++] - *(v[2]);
			vcheck.z = 0;
			dist = vcheck.norm();
			if (dist > maxdist)	maxdist = dist;
			//nlassert(vcheck.norm() < 0.1f);
		}

		//element.Normal = ((*(v[1])-*(v[0])) ^ (*(v[2])-*(v[0]))).normed();
		element.Normal = normals[el];


		// search the vertices in the map
		for (i=0; i<3; ++i)
		{
			// if doesn't exist, create a new vertex
			if ((vremapit = vremap.find(v[i])) == vremap.end())
			{
				element.Tri[i] = (uint32)_Vertices.size();
				_Vertices.push_back(*(v[i]));
				vremap.insert(make_pair(v[i], element.Tri[i]));
			}
			// else use previous
			else
			{
				element.Tri[i] = vremapit->second;
			}
		}

		// setup the vertices pointer
		element.Vertices = &_Vertices;

		CTessFace		*edge[3];

		edge[0] = face->FBase;
		edge[1] = face->FRight;
		edge[2] = face->FLeft;

		for (i=0; i<3; ++i)
		{
			fremapit = fremap.find(edge[i]);
			element.EdgeLinks[i] = (fremapit != fremap.end() ? fremapit->second : NULL);
		}
	}

	for (el=0; el<(sint)_Tessellation.size(); ++el)
	{
		// add the element to the list of valid elements
		Elements.push_back(&(_Tessellation[el]));
	}

	landscape.clear();
}
Пример #2
0
///////////////////////////////////////////////////////////////
//
// CResourceChecker::CheckLuaSourceForIssues
//
// Look for function names not in comment blocks
// Note: Ignores quotes
//
///////////////////////////////////////////////////////////////
void CResourceChecker::CheckLuaSourceForIssues ( string strLuaSource, const string& strFileName, const string& strResourceName, bool bClientScript, bool bCompiledScript, ECheckerModeType checkerMode, string* pstrOutResult )
{
    CHashMap < SString, long > doneWarningMap;
    long lLineNumber = 1;
    // Check if this is a UTF-8 script
    bool bUTF8 = IsUTF8BOM( strLuaSource.c_str(), strLuaSource.length() );

    // If it's not a UTF8 script, does it contain foreign language characters that should be upgraded?
    if ( !bCompiledScript && !bUTF8 && GetUTF8Confidence ( (const unsigned char*)&strLuaSource.at ( 0 ), strLuaSource.length() ) < 80 )
    {
        std::wstring strUTF16Script = ANSIToUTF16 ( strLuaSource );
#ifdef WIN32
        std::setlocale(LC_CTYPE,""); // Temporarilly use locales to read the script
        std::string strUTFScript = UTF16ToMbUTF8 ( strUTF16Script );
        std::setlocale(LC_CTYPE,"C");
#else
        std::string strUTFScript = UTF16ToMbUTF8 ( strUTF16Script );
#endif
        if ( strLuaSource.length () != strUTFScript.size() )
        {
            // In-place upgrade...
            if ( checkerMode == ECheckerMode::UPGRADE )
            {
                // Upgrade only if there is no problem ( setlocale() issue? )
                if ( strUTF16Script != L"?" )
                {
                    // Convert our script to ANSI, appending a BOM at the beginning
                    strLuaSource = "\xEF\xBB\xBF" + strUTFScript;
                }
            }
            if ( checkerMode == ECheckerMode::WARNINGS )
            {
                m_ulDeprecatedWarningCount++;
                CLogger::LogPrintf ( "WARNING: %s/%s [%s] is encoded in ANSI instead of UTF-8.  Please convert your file to UTF-8.\n", strResourceName.c_str (), strFileName.c_str (), bClientScript ? "Client" : "Server" );
            }
        }
    }

    // Step through each identifier in the file.
    for ( long lPos = 0 ; lPos < (long)strLuaSource.length () ; lPos++ )
    {
        long lNameLength;
        long lNameOffset = FindLuaIdentifier ( strLuaSource.c_str () + lPos, &lNameLength, &lLineNumber );

        if ( lNameOffset == - 1 )
            break;

        lNameOffset += lPos;                // Make offset absolute from the start of the file
        lPos = lNameOffset + lNameLength;   // Adjust so the next pass starts from just after this identifier

        string strIdentifierName( strLuaSource.c_str () + lNameOffset, lNameLength );

        // In-place upgrade...
        if ( checkerMode == ECheckerMode::UPGRADE )
        {
            assert ( !bCompiledScript );

            string strUpgraded;
            if ( UpgradeLuaFunctionName( strIdentifierName, bClientScript, strUpgraded ) )
            {
                // Old head
                string strHead( strLuaSource.c_str (), lNameOffset );
                // Old tail
                string strTail( strLuaSource.c_str () + lNameOffset + lNameLength );
                // New source
                strLuaSource = strHead + strUpgraded + strTail;

                lPos += -lNameLength + strUpgraded.length ();
            }
            CheckVersionRequirements ( strIdentifierName, bClientScript );
        }

        // Log warnings...
        if ( checkerMode == ECheckerMode::WARNINGS )
        {
            // Only do the identifier once per file
            if ( doneWarningMap.find ( strIdentifierName ) == doneWarningMap.end () )
            {
                doneWarningMap[strIdentifierName] = 1;
                if ( !bCompiledScript ) // Don't issue deprecated function warnings if the script is compiled, because we can't upgrade it
                    IssueLuaFunctionNameWarnings ( strIdentifierName, strFileName, strResourceName, bClientScript, lLineNumber );
                CheckVersionRequirements ( strIdentifierName, bClientScript );
            }
        }
    }

    if ( pstrOutResult )
        *pstrOutResult = strLuaSource;
}