forked from mirrors/0ad
207d1367ec
- The server will no longer send a new turn until the previous one has been "acknowledged". (TODO: this may create lag between turns in its current form; investigate and possibly allow executing two turns while the third is being negotiated). - Mutexes are now being used in NetServer and NetClient to ensure commands go into the right batches. - Commented out some orders in the GUI code that should not be there and are not 100% working anyway (they were part of the follow/formation system). - Units that spawn or are created by scripts now have net-safe position and orientation. - Added a debug flag that can be turned on to print details about when commands are received and executed (DEBUG_SYNCHRONIZATION). This is especially useful if you diff the stdouts of two running games. There should be no differences if everything is in synch. This was SVN commit r5463.
160 lines
4.9 KiB
C++
160 lines
4.9 KiB
C++
//Location.cpp
|
|
|
|
#include "precompiled.h"
|
|
|
|
#include <cstdlib>
|
|
#include <math.h>
|
|
#include "se_dcdt.h"
|
|
#include <fstream>
|
|
|
|
//the list of unprocessed triangles
|
|
template <class T>
|
|
SrArray<SeLinkFace<T> *> SeLinkFace<T>::processing;
|
|
|
|
//DJD: Point location function definitions {
|
|
|
|
//initializes each sector midpoint to point to the triangle in which it is contained
|
|
void SeDcdt::InitializeSectors()
|
|
{
|
|
#if defined EXPERIMENT
|
|
//count the number of triangles
|
|
int num = 0;
|
|
#endif
|
|
//calculate the width and height of the triangulation
|
|
float width = _xmax - _xmin;
|
|
float height = _ymax - _ymin;
|
|
//calculate the width and height of each sector
|
|
sectorWidth = width / (float)xSectors;
|
|
sectorHeight = height / (float)ySectors;
|
|
//initialize all sectors to null
|
|
for (int i = 0; i < ySectors; i++)
|
|
{
|
|
for (int j = 0; j < xSectors; j++)
|
|
{
|
|
sectors[i][j] = NULL;
|
|
}
|
|
}
|
|
float x, y;
|
|
float x1, y1, x2, y2, x3, y3;
|
|
//go through the unprocessed triangles
|
|
for (int k = 0; k < SeDcdtFace::Faces(); k++)
|
|
{
|
|
//retrieve the next valid triangle
|
|
SeDcdtFace *currentFace = SeDcdtFace::Face(k);
|
|
if (currentFace == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
#if defined EXPERIMENT
|
|
//keep track of the number of triangles
|
|
num++;
|
|
#endif
|
|
//get the minimum and maximum x and y values
|
|
TriangleVertices(currentFace, x1, y1, x2, y2, x3, y3);
|
|
float left = Min(x1, x2, x3);
|
|
float right = Max(x1, x2, x3);
|
|
float top = Min(y1, y2, y3);
|
|
float bottom = Max(y1, y2, y3);
|
|
//calculate the minimum and maximum x and y sector indices covered
|
|
int xIndexMin = (int)((left - _xmin + 0.5f * sectorWidth) / sectorWidth);
|
|
int xIndexMax = (int)((right - _xmin - 0.5f * sectorWidth) / sectorWidth);
|
|
int yIndexMin = (int)((top - _ymin + 0.5f * sectorHeight) / sectorHeight);
|
|
int yIndexMax = (int)((bottom - _ymin - 0.5f * sectorHeight) / sectorHeight);
|
|
//go through the covered sector midpoints
|
|
for (int i = yIndexMin; i <= yIndexMax; i++)
|
|
{
|
|
for (int j = xIndexMin; j <= xIndexMax; j++)
|
|
{
|
|
//calculate the location of the midpoint
|
|
x = ((float)j + 0.5f) * sectorWidth + _xmin;
|
|
y = ((float)i + 0.5f) * sectorHeight + _ymin;
|
|
//if the midpoint is in the current triangle,
|
|
if (InTriangle(currentFace, x, y))
|
|
{
|
|
//point the sector to that triangle
|
|
sectors[i][j] = currentFace;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#if defined EXPERIMENT
|
|
//if we are running an experiment, output the number of triangles to a data file
|
|
std::ofstream outFile("Data.txt", std::ios_base::app);
|
|
outFile << "Triangles: " << num << "\t";
|
|
outFile.close();
|
|
#endif
|
|
}
|
|
|
|
//check if the given point is within a given triangle
|
|
bool SeDcdt::InTriangle(SeDcdtFace *face, float x, float y)
|
|
{
|
|
//get the triangle's vertices
|
|
float x1, y1, x2, y2, x3, y3;
|
|
TriangleVertices(face, x1, y1, x2, y2, x3, y3);
|
|
//check that the point is counterclockwise of all edges
|
|
return ((Orientation(x1, y1, x2, y2, x, y) >= 0)
|
|
&& (Orientation(x2, y2, x3, y3, x, y) >= 0)
|
|
&& (Orientation(x3, y3, x1, y1, x, y) >= 0));
|
|
}
|
|
|
|
//uses the sectors to locate in which triangle the given point lies
|
|
SeTriangulator::LocateResult SeDcdt::LocatePoint(float x, float y, SeBase* &result)
|
|
{
|
|
//calculates the indices of the sector in which the point lies
|
|
int xIndex = (int)((x - _xmin) / sectorWidth);
|
|
int yIndex = (int)((y - _ymin) / sectorHeight);
|
|
//makes sure the indices are within the proper bounds
|
|
xIndex = (xIndex < 0) ? 0 : (xIndex >= xSectors) ? xSectors - 1 : xIndex;
|
|
yIndex = (yIndex < 0) ? 0 : (yIndex >= ySectors) ? ySectors - 1 : yIndex;
|
|
//retrieve the triangle in which that sector midpoint is located
|
|
SeFace *iniface = sectors[yIndex][xIndex];
|
|
//if it was invalid, start at the usual place
|
|
if (iniface == NULL)
|
|
{
|
|
iniface = _search_face();
|
|
}
|
|
//use this starting triangle to start point location
|
|
return _triangulator->locate_point(iniface, x, y, result);
|
|
}
|
|
|
|
//locate the given point starting at the usual place
|
|
SeTriangulator::LocateResult SeDcdt::LocatePointOld(float x, float y, SeBase* &result)
|
|
{
|
|
return _triangulator->locate_point(_search_face(), x, y, result);
|
|
}
|
|
|
|
//returns the maximum of the 3 values passed
|
|
float SeDcdt::Max(float a, float b, float c)
|
|
{
|
|
return ((a >= b) && (a >= c)) ? a :
|
|
((b >= a) && (b >= c)) ? b : c;
|
|
}
|
|
|
|
//returns the minimum of the 3 values passed
|
|
float SeDcdt::Min(float a, float b, float c)
|
|
{
|
|
return ((a <= b) && (a <= c)) ? a :
|
|
((b <= a) && (b <= c)) ? b : c;
|
|
}
|
|
|
|
//return a random value in the range of x values (used for testing)
|
|
float SeDcdt::RandomX()
|
|
{
|
|
return RandomBetween(_xmin, _xmax);
|
|
}
|
|
|
|
//return a random value in the range of y values (used for testing)
|
|
float SeDcdt::RandomY()
|
|
{
|
|
return RandomBetween(_ymin, _ymax);
|
|
}
|
|
|
|
//returns a random number between the values given
|
|
float SeDcdt::RandomBetween(float min, float max)
|
|
{
|
|
float base = (float)rand() / (float)RAND_MAX; // TODO: Make net-safe
|
|
return (base * (max - min) + min);
|
|
}
|
|
|
|
//Point location function definitions }
|