<commit_before>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.0.0, packaged on August, 2008.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_mesh2.cpp implementation of the GLC_Mesh2 class.

#include "glc_mesh2.h"
#include "glc_openglexception.h"
#include "glc_selectionmaterial.h"

#include <QtDebug>

//////////////////////////////////////////////////////////////////////
// Constructor Destructor
//////////////////////////////////////////////////////////////////////
GLC_Mesh2::GLC_Mesh2()
:GLC_Geometry("Mesh", false)
, m_CoordinateHash()
, m_CoordinateIndex()
, m_MaterialHash()
, m_MaterialIndex()
, m_NormalHash()
, m_NormalIndex()
, m_TextCoordinateHash()
, m_TextureIndex()
, m_NumberOfFaces(0)
, m_SelectionListID(0)
, m_IsSelected(false)
{
	//qDebug() << "GLC_Mesh2::GLC_Mesh2" << getID();
}

GLC_Mesh2::GLC_Mesh2(const GLC_Mesh2 &meshToCopy)
: GLC_Geometry(meshToCopy)
, m_CoordinateHash(meshToCopy.m_CoordinateHash)
, m_CoordinateIndex(meshToCopy.m_CoordinateIndex)
, m_MaterialHash(meshToCopy.m_MaterialHash)
, m_MaterialIndex(meshToCopy.m_MaterialIndex)
, m_NormalHash(meshToCopy.m_NormalHash)
, m_NormalIndex(meshToCopy.m_NormalIndex)
, m_TextCoordinateHash(meshToCopy.m_TextCoordinateHash)
, m_TextureIndex(meshToCopy.m_TextureIndex)
, m_NumberOfFaces(meshToCopy.m_NumberOfFaces)
, m_SelectionListID(0)
, m_IsSelected(false)
{
	//qDebug() << "GLC_Mesh2::GLC_Mesh2" << getID();
	// Add this mesh to inner material
	MaterialHash::const_iterator i= m_MaterialHash.begin();
    while (i != m_MaterialHash.constEnd())
    {
        // update inner material use table
        i.value()->addGLC_Geom(this);
        ++i;
    }
}

GLC_Mesh2::~GLC_Mesh2(void)
{
	//qDebug() << "GLC_Mesh2::~GLC_Mesh2" << getID();
	m_CoordinateHash.clear();
	m_CoordinateIndex.clear();

	m_NormalHash.clear();
	m_NormalIndex.clear();

	m_TextCoordinateHash.clear();
	m_TextureIndex.clear();

	// delete mesh inner material
	MaterialHash::const_iterator i= m_MaterialHash.begin();
    while (i != m_MaterialHash.constEnd())
    {
        // delete the material if necessary
        i.value()->delGLC_Geom(getID());
        if (i.value()->isUnused()) delete i.value();
        ++i;
    }
	m_MaterialHash.clear();
	m_MaterialIndex.clear();

	// If display list is valid : delete it
	if (0 != m_SelectionListID)
	{
		glDeleteLists(m_SelectionListID, 1);
	}

}
/////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

//! Return material index if Material is the same than a material already in the mesh
int GLC_Mesh2::materialIndex(const GLC_Material& mat) const
{
	int index= -1;
	MaterialHash::const_iterator iEntry= m_MaterialHash.begin();

    while ((iEntry != m_MaterialHash.constEnd()) and !(*(iEntry.value()) == mat))
    {
        ++iEntry;
    }
    if (iEntry != m_MaterialHash.constEnd())
    {
    	index= iEntry.key();
    }
	return index;

}

// return the mesh bounding box
GLC_BoundingBox* GLC_Mesh2::getBoundingBox(void) const
{
	GLC_BoundingBox* pBoundingBox= new GLC_BoundingBox();

	Vector3dHash::const_iterator iEntry= m_CoordinateHash.begin();

    while (iEntry != m_CoordinateHash.constEnd())
    {
        // Combine the vertex with the bounding box
        pBoundingBox->combine(iEntry.value());
        ++iEntry;
    }

	return pBoundingBox;
}

// Return a copy of the current geometry
GLC_Geometry* GLC_Mesh2::clone() const
{
	return new GLC_Mesh2(*this);
}

/////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Add material to mesh
void GLC_Mesh2::addMaterial(int Index, GLC_Material* pMaterial)
{
	if (pMaterial != NULL)
	{
		MaterialHash::const_iterator iMaterial= m_MaterialHash.find(Index);
		// Check if there is a material at specified index
		Q_ASSERT(iMaterial == m_MaterialHash.end());

		// Add this geometry in the material use table
		pMaterial->addGLC_Geom(this);
		// Add the Material to Material hash table
		m_MaterialHash.insert(Index, pMaterial);
		// Test if the material is transparent
		if (pMaterial->isTransparent() && (m_MaterialHash.size() == 1))
		{
			setTransparency(true);
		}
		else if (isTransparent() && !pMaterial->isTransparent())
		{
			setTransparency(false);
		}
		// Invalid the geometry
		m_GeometryIsValid = false;
		m_ListIsValid= false;	// GLC_Mesh2 compatibility
	}
}

// Remove material from the mesh
int GLC_Mesh2::removeMaterial(int index)
{
	//qDebug() << "GLC_Mesh2::removeMaterial" << getID();
	m_MaterialHash[index]->delGLC_Geom(getID());
	// If the removed material is the last, change transparency
	if((m_MaterialHash.size() == 1) && !getMaterial()->isTransparent())
	{
		setTransparency(false);
	}
	return m_MaterialHash.remove(index);
}

// Reverse mesh normal
void GLC_Mesh2::reverseNormal()
{
	Vector3dHash::iterator iNormal= m_NormalHash.begin();
    while (iNormal != m_NormalHash.constEnd())
    {
        // Reverse normal
        iNormal.value().setInv();
        ++iNormal;
    }
    m_ListIsValid= false;

}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////
// if the geometry have a texture, load it
void GLC_Mesh2::glLoadTexture(void)
{
	// Load texture of the master material
	m_pMaterial->glLoadTexture();

	MaterialHash::iterator iMaterial= m_MaterialHash.begin();

    while (iMaterial != m_MaterialHash.constEnd())
    {
        // Load texture of mesh materials
        iMaterial.value()->glLoadTexture();
        ++iMaterial;
    }
}

// Specific glExecute method
void GLC_Mesh2::glExecute(GLenum Mode, bool isSelected, bool forceWire)
{

	if (isSelected)
	{
		m_IsSelected= true;
		// Define Geometry's property
		glPropGeom(isSelected, forceWire);

		// Geometry validity set to true
		m_GeometryIsValid= true;

		if (!m_ListIsValid)
		{
			// The list is not up to date or doesn't exist

			createList(Mode);
		}
		else
		{
			glCallList(m_SelectionListID);
		}

		// OpenGL error handler
		GLenum error= glGetError();
		if (error != GL_NO_ERROR)
		{
			GLC_OpenGlException OpenGlException("GLC_Geometry::GlExecute ", error);
			throw(OpenGlException);
		}
		m_IsSelected= false;
	}
	else
	{
		GLC_Geometry::glExecute(Mode, isSelected, forceWire);
	}
}

// Specific createList method
void GLC_Mesh2::createList(GLenum Mode)
{
	createSelectionList(Mode);
	GLC_Geometry::createList(Mode);
}

// Create selection list
void GLC_Mesh2::createSelectionList(GLenum Mode)
{
	m_IsSelected= true;
	if(!m_SelectionListID)		// The list doesn't exist
	{
		m_SelectionListID= glGenLists(1);
		Q_ASSERT(0 != m_SelectionListID);
	}
	// List setting up
	glNewList(m_SelectionListID, Mode);
		// Geometry set up and display
		glDraw();	// Virtual function defined in concrete class
	glEndList();
	m_IsSelected= false;
	// OpenGL error handler
	GLenum error= glGetError();
	if (error != GL_NO_ERROR)
	{
		GLC_OpenGlException OpenGlException("GLC_Mesh2::createList ", error);
		throw(OpenGlException);
	}
}

// Virtual interface for OpenGL Geometry set up.
void GLC_Mesh2::glDraw()
{
	//qDebug() << "GLC_Mesh2::glDraw ENTER";

	// If the mesh is empty there is noting to do
	if (m_CoordinateIndex.isEmpty()) return;

	// Index face separator
	const int separator= -1;

	int CurrentMaterialIndex= -1;
	bool IsNewFace= true;

	for(int i=0; i < m_CoordinateIndex.size(); ++i)
	{
		if (m_CoordinateIndex.at(i) == separator)
		{
			Q_ASSERT((i != 0) && (!IsNewFace));	// the first index couldn't be a separator
			// End of current face
			glEnd();
			// At the next round a new face will be create
			IsNewFace=true;
		}
		else
		{
			if (CurrentMaterialIndex != m_MaterialIndex.at(i))
			{	// If the material change, make it current
				CurrentMaterialIndex= m_MaterialIndex.at(i);
				//qDebug() << "GLC_Mesh2::glDraw : CurrentMaterialIndex" << CurrentMaterialIndex;
				MaterialHash::const_iterator iMaterial= m_MaterialHash.find(CurrentMaterialIndex);
				// Check if the key is already use
				if (iMaterial != m_MaterialHash.end())
				{
					if (!m_IsSelected or (m_IsSelected and m_MaterialHash[CurrentMaterialIndex]->getAddRgbaTexture()))
					{
						m_MaterialHash[CurrentMaterialIndex]->glExecute();
					}

					if (m_IsSelected) GLC_SelectionMaterial::glExecute();
				}
				else
				{
					m_pMaterial->glExecute();
					if (m_IsSelected) GLC_SelectionMaterial::glExecute();
				}
			}

			if (IsNewFace)
			{
				if ((m_MaterialHash.find(CurrentMaterialIndex) != m_MaterialHash.end()) and m_MaterialHash[CurrentMaterialIndex]->getAddRgbaTexture())
				{
					glEnable(GL_TEXTURE_2D);
					//qDebug() << "GLC_Mesh2::glDraw : Texture enabled";
				}
				else
				{
					glDisable(GL_TEXTURE_2D);
				}
				IsNewFace= false;
				// New polygon creation
				glBegin(GL_POLYGON);
			} // end if isNewFace

			// Vertex texture coordinate if necessary
			if (i < m_TextureIndex.size())
			{
				glTexCoord2fv(m_TextCoordinateHash[m_TextureIndex.at(i)].return_dVect());
			}

			// Vertex Normal
			Q_ASSERT(i < m_NormalIndex.size());
			glNormal3fv(m_NormalHash[m_NormalIndex.at(i)].return_dVect());

			// Vertex 3D coordinate
			Q_ASSERT(i < m_CoordinateIndex.size());
			glVertex3fv(m_CoordinateHash[m_CoordinateIndex.at(i)].return_dVect());
		}
	}

	// OpenGL error handler
	GLenum error= glGetError();
	if (error != GL_NO_ERROR)
	{
		GLC_OpenGlException OpenGlException("GLC_Mesh2::GlDraw ", error);
		throw(OpenGlException);
	}

}
<commit_msg>When creating list, selectionList is always created in compile mode.<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.0.0, packaged on August, 2008.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_mesh2.cpp implementation of the GLC_Mesh2 class.

#include "glc_mesh2.h"
#include "glc_openglexception.h"
#include "glc_selectionmaterial.h"

#include <QtDebug>

//////////////////////////////////////////////////////////////////////
// Constructor Destructor
//////////////////////////////////////////////////////////////////////
GLC_Mesh2::GLC_Mesh2()
:GLC_Geometry("Mesh", false)
, m_CoordinateHash()
, m_CoordinateIndex()
, m_MaterialHash()
, m_MaterialIndex()
, m_NormalHash()
, m_NormalIndex()
, m_TextCoordinateHash()
, m_TextureIndex()
, m_NumberOfFaces(0)
, m_SelectionListID(0)
, m_IsSelected(false)
{
	//qDebug() << "GLC_Mesh2::GLC_Mesh2" << getID();
}

GLC_Mesh2::GLC_Mesh2(const GLC_Mesh2 &meshToCopy)
: GLC_Geometry(meshToCopy)
, m_CoordinateHash(meshToCopy.m_CoordinateHash)
, m_CoordinateIndex(meshToCopy.m_CoordinateIndex)
, m_MaterialHash(meshToCopy.m_MaterialHash)
, m_MaterialIndex(meshToCopy.m_MaterialIndex)
, m_NormalHash(meshToCopy.m_NormalHash)
, m_NormalIndex(meshToCopy.m_NormalIndex)
, m_TextCoordinateHash(meshToCopy.m_TextCoordinateHash)
, m_TextureIndex(meshToCopy.m_TextureIndex)
, m_NumberOfFaces(meshToCopy.m_NumberOfFaces)
, m_SelectionListID(0)
, m_IsSelected(false)
{
	//qDebug() << "GLC_Mesh2::GLC_Mesh2" << getID();
	// Add this mesh to inner material
	MaterialHash::const_iterator i= m_MaterialHash.begin();
    while (i != m_MaterialHash.constEnd())
    {
        // update inner material use table
        i.value()->addGLC_Geom(this);
        ++i;
    }
}

GLC_Mesh2::~GLC_Mesh2(void)
{
	//qDebug() << "GLC_Mesh2::~GLC_Mesh2" << getID();
	m_CoordinateHash.clear();
	m_CoordinateIndex.clear();

	m_NormalHash.clear();
	m_NormalIndex.clear();

	m_TextCoordinateHash.clear();
	m_TextureIndex.clear();

	// delete mesh inner material
	MaterialHash::const_iterator i= m_MaterialHash.begin();
    while (i != m_MaterialHash.constEnd())
    {
        // delete the material if necessary
        i.value()->delGLC_Geom(getID());
        if (i.value()->isUnused()) delete i.value();
        ++i;
    }
	m_MaterialHash.clear();
	m_MaterialIndex.clear();

	// If display list is valid : delete it
	if (0 != m_SelectionListID)
	{
		glDeleteLists(m_SelectionListID, 1);
	}

}
/////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

//! Return material index if Material is the same than a material already in the mesh
int GLC_Mesh2::materialIndex(const GLC_Material& mat) const
{
	int index= -1;
	MaterialHash::const_iterator iEntry= m_MaterialHash.begin();

    while ((iEntry != m_MaterialHash.constEnd()) and !(*(iEntry.value()) == mat))
    {
        ++iEntry;
    }
    if (iEntry != m_MaterialHash.constEnd())
    {
    	index= iEntry.key();
    }
	return index;

}

// return the mesh bounding box
GLC_BoundingBox* GLC_Mesh2::getBoundingBox(void) const
{
	GLC_BoundingBox* pBoundingBox= new GLC_BoundingBox();

	Vector3dHash::const_iterator iEntry= m_CoordinateHash.begin();

    while (iEntry != m_CoordinateHash.constEnd())
    {
        // Combine the vertex with the bounding box
        pBoundingBox->combine(iEntry.value());
        ++iEntry;
    }

	return pBoundingBox;
}

// Return a copy of the current geometry
GLC_Geometry* GLC_Mesh2::clone() const
{
	return new GLC_Mesh2(*this);
}

/////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Add material to mesh
void GLC_Mesh2::addMaterial(int Index, GLC_Material* pMaterial)
{
	if (pMaterial != NULL)
	{
		MaterialHash::const_iterator iMaterial= m_MaterialHash.find(Index);
		// Check if there is a material at specified index
		Q_ASSERT(iMaterial == m_MaterialHash.end());

		// Add this geometry in the material use table
		pMaterial->addGLC_Geom(this);
		// Add the Material to Material hash table
		m_MaterialHash.insert(Index, pMaterial);
		// Test if the material is transparent
		if (pMaterial->isTransparent() && (m_MaterialHash.size() == 1))
		{
			setTransparency(true);
		}
		else if (isTransparent() && !pMaterial->isTransparent())
		{
			setTransparency(false);
		}
		// Invalid the geometry
		m_GeometryIsValid = false;
		m_ListIsValid= false;	// GLC_Mesh2 compatibility
	}
}

// Remove material from the mesh
int GLC_Mesh2::removeMaterial(int index)
{
	//qDebug() << "GLC_Mesh2::removeMaterial" << getID();
	m_MaterialHash[index]->delGLC_Geom(getID());
	// If the removed material is the last, change transparency
	if((m_MaterialHash.size() == 1) && !getMaterial()->isTransparent())
	{
		setTransparency(false);
	}
	return m_MaterialHash.remove(index);
}

// Reverse mesh normal
void GLC_Mesh2::reverseNormal()
{
	Vector3dHash::iterator iNormal= m_NormalHash.begin();
    while (iNormal != m_NormalHash.constEnd())
    {
        // Reverse normal
        iNormal.value().setInv();
        ++iNormal;
    }
    m_ListIsValid= false;

}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////
// if the geometry have a texture, load it
void GLC_Mesh2::glLoadTexture(void)
{
	// Load texture of the master material
	m_pMaterial->glLoadTexture();

	MaterialHash::iterator iMaterial= m_MaterialHash.begin();

    while (iMaterial != m_MaterialHash.constEnd())
    {
        // Load texture of mesh materials
        iMaterial.value()->glLoadTexture();
        ++iMaterial;
    }
}

// Specific glExecute method
void GLC_Mesh2::glExecute(GLenum Mode, bool isSelected, bool forceWire)
{

	if (isSelected)
	{
		m_IsSelected= true;
		// Define Geometry's property
		glPropGeom(isSelected, forceWire);

		// Geometry validity set to true
		m_GeometryIsValid= true;

		if (!m_ListIsValid)
		{
			// The list is not up to date or doesn't exist

			createList(Mode);
		}
		else
		{
			glCallList(m_SelectionListID);
		}

		// OpenGL error handler
		GLenum error= glGetError();
		if (error != GL_NO_ERROR)
		{
			GLC_OpenGlException OpenGlException("GLC_Geometry::GlExecute ", error);
			throw(OpenGlException);
		}
		m_IsSelected= false;
	}
	else
	{
		GLC_Geometry::glExecute(Mode, isSelected, forceWire);
	}
}

// Specific createList method
void GLC_Mesh2::createList(GLenum Mode)
{
	createSelectionList(GL_COMPILE);
	GLC_Geometry::createList(Mode);
}

// Create selection list
void GLC_Mesh2::createSelectionList(GLenum Mode)
{
	m_IsSelected= true;
	if(!m_SelectionListID)		// The list doesn't exist
	{
		m_SelectionListID= glGenLists(1);
		Q_ASSERT(0 != m_SelectionListID);
	}
	// List setting up
	glNewList(m_SelectionListID, Mode);
		// Geometry set up and display
		glDraw();	// Virtual function defined in concrete class
	glEndList();
	m_IsSelected= false;
	// OpenGL error handler
	GLenum error= glGetError();
	if (error != GL_NO_ERROR)
	{
		GLC_OpenGlException OpenGlException("GLC_Mesh2::createList ", error);
		throw(OpenGlException);
	}
}

// Virtual interface for OpenGL Geometry set up.
void GLC_Mesh2::glDraw()
{
	//qDebug() << "GLC_Mesh2::glDraw ENTER";

	// If the mesh is empty there is noting to do
	if (m_CoordinateIndex.isEmpty()) return;

	// Index face separator
	const int separator= -1;

	int CurrentMaterialIndex= -1;
	bool IsNewFace= true;

	for(int i=0; i < m_CoordinateIndex.size(); ++i)
	{
		if (m_CoordinateIndex.at(i) == separator)
		{
			Q_ASSERT((i != 0) && (!IsNewFace));	// the first index couldn't be a separator
			// End of current face
			glEnd();
			// At the next round a new face will be create
			IsNewFace=true;
		}
		else
		{
			if (CurrentMaterialIndex != m_MaterialIndex.at(i))
			{	// If the material change, make it current
				CurrentMaterialIndex= m_MaterialIndex.at(i);
				//qDebug() << "GLC_Mesh2::glDraw : CurrentMaterialIndex" << CurrentMaterialIndex;
				MaterialHash::const_iterator iMaterial= m_MaterialHash.find(CurrentMaterialIndex);
				// Check if the key is already use
				if (iMaterial != m_MaterialHash.end())
				{
					if (!m_IsSelected or (m_IsSelected and m_MaterialHash[CurrentMaterialIndex]->getAddRgbaTexture()))
					{
						m_MaterialHash[CurrentMaterialIndex]->glExecute();
					}

					if (m_IsSelected) GLC_SelectionMaterial::glExecute();
				}
				else
				{
					m_pMaterial->glExecute();
					if (m_IsSelected) GLC_SelectionMaterial::glExecute();
				}
			}

			if (IsNewFace)
			{
				if ((m_MaterialHash.find(CurrentMaterialIndex) != m_MaterialHash.end()) and m_MaterialHash[CurrentMaterialIndex]->getAddRgbaTexture())
				{
					glEnable(GL_TEXTURE_2D);
					//qDebug() << "GLC_Mesh2::glDraw : Texture enabled";
				}
				else
				{
					glDisable(GL_TEXTURE_2D);
				}
				IsNewFace= false;
				// New polygon creation
				glBegin(GL_POLYGON);
			} // end if isNewFace

			// Vertex texture coordinate if necessary
			if (i < m_TextureIndex.size())
			{
				glTexCoord2fv(m_TextCoordinateHash[m_TextureIndex.at(i)].return_dVect());
			}

			// Vertex Normal
			Q_ASSERT(i < m_NormalIndex.size());
			glNormal3fv(m_NormalHash[m_NormalIndex.at(i)].return_dVect());

			// Vertex 3D coordinate
			Q_ASSERT(i < m_CoordinateIndex.size());
			glVertex3fv(m_CoordinateHash[m_CoordinateIndex.at(i)].return_dVect());
		}
	}

	// OpenGL error handler
	GLenum error= glGetError();
	if (error != GL_NO_ERROR)
	{
		GLC_OpenGlException OpenGlException("GLC_Mesh2::GlDraw ", error);
		throw(OpenGlException);
	}

}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "app/version.h"
#include "console/console.h"

static const U32 csgVersionNumber = TORQUE_GAME_ENGINE;

U32 getVersionNumber()
{
   return csgVersionNumber;
}

const char* getVersionString()
{
   return TORQUE_GAME_ENGINE_VERSION_STRING;
}

/// TGE       0001
/// TGEA      0002
/// TGB       0003
/// TGEA 360  0004
/// TGE  WII  0005
/// Torque 3D 0006

const char* getEngineProductString()
{
#ifndef TORQUE_ENGINE_PRODUCT
   return "Torque Engine";
#else
   switch (TORQUE_ENGINE_PRODUCT)
   {
      case 0001:
         return "Torque Game Engine";
      case 0002:
         return "Torque Game Engine Advanced";
      case 0003:
         return "Torque 2D";
      case 0004:
         return "Torque 360";
      case 0005:
         return "Torque for Wii";
      case 0006:
         return "Torque 3D";

      default:
         return "Torque Engine";
   };
#endif
}

const char* getCompileTimeString()
{
   return __DATE__ " at " __TIME__;
}
//----------------------------------------------------------------

ConsoleFunctionGroupBegin( CompileInformation, "Functions to get version information about the current executable." );

ConsoleFunction( getVersionNumber, S32, 1, 1, "Get the version of the build, as a string.\n\n"
				"@ingroup Debugging")
{
   return getVersionNumber();
}

ConsoleFunction( getVersionString, const char*, 1, 1, "Get the version of the build, as a string.\n\n"
				"@ingroup Debugging")
{
   return getVersionString();
}

ConsoleFunction( getEngineName, const char*, 1, 1, "Get the name of the engine product that this is running from, as a string.\n\n"
				"@ingroup Debugging")
{
   return getEngineProductString();
}

ConsoleFunction( getCompileTimeString, const char*, 1, 1, "Get the time of compilation.\n\n"
				"@ingroup Debugging")
{
   return getCompileTimeString();
}

ConsoleFunction( getBuildString, const char*, 1, 1, "Get the type of build, \"Debug\" or \"Release\".\n\n"
				"@ingroup Debugging")
{
#ifdef TORQUE_DEBUG
   return "Debug";
#else
   return "Release";
#endif
}

ConsoleFunctionGroupEnd( CompileInformation );

ConsoleFunction(isDemo, bool, 1, 1, "")
{
#ifdef TORQUE_DEMO
   return true;
#else
   return false;
#endif
}

ConsoleFunction(isWebDemo, bool, 1, 1, "")
{
#ifdef TORQUE_DEMO
   return Platform::getWebDeployment();
#else
   return false;
#endif
}<commit_msg>Fill in missing case for getEngineProductString switch block.<commit_after>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "app/version.h"
#include "console/console.h"

static const U32 csgVersionNumber = TORQUE_GAME_ENGINE;

U32 getVersionNumber()
{
   return csgVersionNumber;
}

const char* getVersionString()
{
   return TORQUE_GAME_ENGINE_VERSION_STRING;
}

/// TGE       0001
/// TGEA      0002
/// TGB       0003
/// TGEA 360  0004
/// TGE  WII  0005
/// Torque 3D 0006

const char* getEngineProductString()
{
#ifndef TORQUE_ENGINE_PRODUCT
   return "Torque Engine";
#else
   switch (TORQUE_ENGINE_PRODUCT)
   {
      case 0001:
         return "Torque Game Engine";
      case 0002:
         return "Torque Game Engine Advanced";
      case 0003:
         return "Torque 2D";
      case 0004:
         return "Torque 360";
      case 0005:
         return "Torque for Wii";
      case 0006:
         return "Torque 3D";
      case 0007:
	     return "Torque 3D MIT";

      default:
         return "Torque Engine";
   };
#endif
}

const char* getCompileTimeString()
{
   return __DATE__ " at " __TIME__;
}
//----------------------------------------------------------------

ConsoleFunctionGroupBegin( CompileInformation, "Functions to get version information about the current executable." );

ConsoleFunction( getVersionNumber, S32, 1, 1, "Get the version of the build, as a string.\n\n"
				"@ingroup Debugging")
{
   return getVersionNumber();
}

ConsoleFunction( getVersionString, const char*, 1, 1, "Get the version of the build, as a string.\n\n"
				"@ingroup Debugging")
{
   return getVersionString();
}

ConsoleFunction( getEngineName, const char*, 1, 1, "Get the name of the engine product that this is running from, as a string.\n\n"
				"@ingroup Debugging")
{
   return getEngineProductString();
}

ConsoleFunction( getCompileTimeString, const char*, 1, 1, "Get the time of compilation.\n\n"
				"@ingroup Debugging")
{
   return getCompileTimeString();
}

ConsoleFunction( getBuildString, const char*, 1, 1, "Get the type of build, \"Debug\" or \"Release\".\n\n"
				"@ingroup Debugging")
{
#ifdef TORQUE_DEBUG
   return "Debug";
#else
   return "Release";
#endif
}

ConsoleFunctionGroupEnd( CompileInformation );

ConsoleFunction(isDemo, bool, 1, 1, "")
{
#ifdef TORQUE_DEMO
   return true;
#else
   return false;
#endif
}

ConsoleFunction(isWebDemo, bool, 1, 1, "")
{
#ifdef TORQUE_DEMO
   return Platform::getWebDeployment();
#else
   return false;
#endif
}<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {XX.tif}
//    OUTPUTS: {XX.txt}
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginLatex
//
//  This example shows the basic approch to perform
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

#include "otbMeanShiftImageFilter.h"
#include "itkLabelImageToLabelMapFilter.h"
#include "otbAttributesMapLabelObject.h"
#include "itkLabelMap.h"
#include "otbShapeAttributesLabelMapFilter.h"
#include "otbStatisticsAttributesLabelMapFilter.h"
#include "otbRadiometricAttributesLabelMapFilter.h"
#include "otbAttributesMapOpeningLabelMapFilter.h"
#include "itkLabelMapToLabelImageFilter.h"

int main(int argc, char * argv[])
{
  if(argc != 10)
    {
      std::cerr<<"Usage: "<<argv[0]<<" reffname outfname attribute_name lowerThan tresh spatialRadius rangeRadius minregionsize scale"<<std::endl;
      return EXIT_FAILURE;
    }

  const char * reffname = argv[1];
  const char * outfname = argv[2];
  const char * attr     = argv[3];
  bool  lowerThan       = atoi(argv[4]);
  double thresh         = atof(argv[5]);

  const unsigned int spatialRadius          = atoi(argv[6]);
  const double       rangeRadius            = atof(argv[7]);
  const unsigned int minRegionSize          = atoi(argv[8]);
  const double       scale                  = atoi(argv[9]);

  const unsigned int Dimension = 2;

  // Labeled image type
  typedef unsigned short                                                 LabelType;
  typedef double                                                         PixelType;
  typedef otb::Image<LabelType,Dimension>                                LabeledImageType;
  typedef otb::Image<PixelType,Dimension>                                ImageType;
  typedef otb::VectorImage<PixelType,Dimension>                          VectorImageType;
  typedef otb::ImageFileReader<LabeledImageType>                         LabeledReaderType;
  typedef otb::ImageFileReader<ImageType>                                ReaderType;
  typedef otb::ImageFileReader<VectorImageType>                          VectorReaderType;
  typedef otb::ImageFileWriter<LabeledImageType>                         WriterType;
  // Label map typedef
  typedef otb::AttributesMapLabelObject<LabelType,Dimension,double>      LabelObjectType;
  typedef itk::LabelMap<LabelObjectType>                                 LabelMapType;
  typedef itk::LabelImageToLabelMapFilter<LabeledImageType,LabelMapType> LabelMapFilterType;
  typedef otb::ShapeAttributesLabelMapFilter<LabelMapType>               ShapeLabelMapFilterType;
  typedef otb::StatisticsAttributesLabelMapFilter<LabelMapType,ImageType> StatisticsLabelMapFilterType;
  typedef otb::RadiometricAttributesLabelMapFilter<LabelMapType,VectorImageType> RadiometricLabelMapFilterType;
  typedef otb::AttributesMapOpeningLabelMapFilter<LabelMapType>          OpeningLabelMapFilterType;
  typedef itk::LabelMapToLabelImageFilter<LabelMapType,LabeledImageType> LabelMapToLabeledImageFilterType;

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(reffname);
//std::cout << reffname << std::endl;
  //reader->Update();
//std::cout << reffname << std::endl;
  VectorReaderType::Pointer vreader = VectorReaderType::New();
  vreader->SetFileName(reffname);

  //Segment the ref image using Mean Shift
  typedef otb::MeanShiftImageFilter<ImageType,ImageType, LabeledImageType> FilterType;
  FilterType::Pointer filter = FilterType::New();
  filter->SetSpatialRadius(spatialRadius);
  filter->SetRangeRadius(rangeRadius);
  filter->SetMinimumRegionSize(minRegionSize);
  filter->SetScale(scale);
  filter->SetInput(reader->GetOutput());

  LabelMapFilterType::Pointer labelMapFilter = LabelMapFilterType::New();
  labelMapFilter->SetInput(filter->GetLabeledClusteredOutput());
  labelMapFilter->SetBackgroundValue(itk::NumericTraits<LabelType>::max());

  ShapeLabelMapFilterType::Pointer shapeLabelMapFilter = ShapeLabelMapFilterType::New();
  shapeLabelMapFilter->SetInput(labelMapFilter->GetOutput());

  StatisticsLabelMapFilterType::Pointer statisticsLabelMapFilter = StatisticsLabelMapFilterType::New();
  statisticsLabelMapFilter->SetInput1(shapeLabelMapFilter->GetOutput());
  statisticsLabelMapFilter->SetInput2(reader->GetOutput());

  statisticsLabelMapFilter->Update();

  RadiometricLabelMapFilterType::Pointer radiometricLabelMapFilter = RadiometricLabelMapFilterType::New();
  radiometricLabelMapFilter->SetInput1(statisticsLabelMapFilter->GetOutput());
  radiometricLabelMapFilter->SetInput2(vreader->GetOutput());
  //radiometricLabelMapFilter->SetReducedAttributeSet(false);
  radiometricLabelMapFilter->SetRedChannelIndex(1);
  radiometricLabelMapFilter->SetNIRChannelIndex(2);
  radiometricLabelMapFilter->Update();

  OpeningLabelMapFilterType::Pointer opening = OpeningLabelMapFilterType::New();
  opening->SetInput(radiometricLabelMapFilter->GetOutput());
  opening->SetAttributeName(attr);
  opening->SetReverseOrdering(lowerThan);
  opening->SetLambda(thresh);

  LabelMapToLabeledImageFilterType::Pointer labelMap2LabeledImage = LabelMapToLabeledImageFilterType::New();
  labelMap2LabeledImage->SetInput(opening->GetOutput());

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outfname);
  writer->SetInput(labelMap2LabeledImage->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}
<commit_msg>DOC:obia<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {XX.tif}
//    OUTPUTS: {XX.txt}
//  Software Guide : EndCommandLineArgs

//  Software Guide : BeginLatex
//
//  This example shows the basic approch to perform object based analysis on a image.
//  The input image is firstly segmented using the \doxygen{otb}{MeanShiftImageFilter}
//  Then each segmented region is converted to a Map of labeled objects.
//  After the \doxygen{otb}{RadiometricAttributesLabelMapFilter}  computes computes
//  radiometric attributes for each object.
//  Images are supposed to be standard 4-bands image (B,G,R,NIR). The
//  index of each channel can be set via the Set***ChannelIndex()
//  accessors.
//
//  This filter internally applies the
//  StatisticsAttributesLabelMapFilter to the following features:
  //  \begin{itemize}
  //  \item GEMI
  //  \item NDVI
  //  \item IR
  //  \item IC
  //  \item IB
  //  \item NDWI2
  //  \item Intensity
  //  \item and original B, G, R and NIR channels
  //  \end{itemize},
//
//
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

#include "otbMeanShiftImageFilter.h"
#include "itkLabelImageToLabelMapFilter.h"
#include "otbAttributesMapLabelObject.h"
#include "itkLabelMap.h"
#include "otbShapeAttributesLabelMapFilter.h"
#include "otbStatisticsAttributesLabelMapFilter.h"
#include "otbRadiometricAttributesLabelMapFilter.h"
#include "otbAttributesMapOpeningLabelMapFilter.h"
#include "itkLabelMapToLabelImageFilter.h"

int main(int argc, char * argv[])
{
  if(argc != 10)
    {
      std::cerr<<"Usage: "<<argv[0]<<" reffname outfname attribute_name lowerThan tresh spatialRadius rangeRadius minregionsize scale"<<std::endl;
      return EXIT_FAILURE;
    }

  const char * reffname = argv[1];
  const char * outfname = argv[2];
  const char * attr     = argv[3];
  bool  lowerThan       = atoi(argv[4]);
  double thresh         = atof(argv[5]);

  const unsigned int spatialRadius          = atoi(argv[6]);
  const double       rangeRadius            = atof(argv[7]);
  const unsigned int minRegionSize          = atoi(argv[8]);
  const double       scale                  = atoi(argv[9]);

  const unsigned int Dimension = 2;

  // Labeled image type
  typedef unsigned short                                                 LabelType;
  typedef double                                                         PixelType;
  typedef otb::Image<LabelType,Dimension>                                LabeledImageType;
  typedef otb::Image<PixelType,Dimension>                                ImageType;
  typedef otb::VectorImage<PixelType,Dimension>                          VectorImageType;
  typedef otb::ImageFileReader<LabeledImageType>                         LabeledReaderType;
  typedef otb::ImageFileReader<ImageType>                                ReaderType;
  typedef otb::ImageFileReader<VectorImageType>                          VectorReaderType;
  typedef otb::ImageFileWriter<LabeledImageType>                         WriterType;
  // Label map typedef
  typedef otb::AttributesMapLabelObject<LabelType,Dimension,double>      LabelObjectType;
  typedef itk::LabelMap<LabelObjectType>                                 LabelMapType;
  typedef itk::LabelImageToLabelMapFilter<LabeledImageType,LabelMapType> LabelMapFilterType;
  typedef otb::ShapeAttributesLabelMapFilter<LabelMapType>               ShapeLabelMapFilterType;
  typedef otb::StatisticsAttributesLabelMapFilter<LabelMapType,ImageType> StatisticsLabelMapFilterType;
  typedef otb::RadiometricAttributesLabelMapFilter<LabelMapType,VectorImageType> RadiometricLabelMapFilterType;
  typedef otb::AttributesMapOpeningLabelMapFilter<LabelMapType>          OpeningLabelMapFilterType;
  typedef itk::LabelMapToLabelImageFilter<LabelMapType,LabeledImageType> LabelMapToLabeledImageFilterType;

  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(reffname);
//std::cout << reffname << std::endl;
  //reader->Update();
//std::cout << reffname << std::endl;
  VectorReaderType::Pointer vreader = VectorReaderType::New();
  vreader->SetFileName(reffname);

  //Segment the ref image using Mean Shift
  typedef otb::MeanShiftImageFilter<ImageType,ImageType, LabeledImageType> FilterType;
  FilterType::Pointer filter = FilterType::New();
  filter->SetSpatialRadius(spatialRadius);
  filter->SetRangeRadius(rangeRadius);
  filter->SetMinimumRegionSize(minRegionSize);
  filter->SetScale(scale);
  filter->SetInput(reader->GetOutput());

  LabelMapFilterType::Pointer labelMapFilter = LabelMapFilterType::New();
  labelMapFilter->SetInput(filter->GetLabeledClusteredOutput());
  labelMapFilter->SetBackgroundValue(itk::NumericTraits<LabelType>::max());

  ShapeLabelMapFilterType::Pointer shapeLabelMapFilter = ShapeLabelMapFilterType::New();
  shapeLabelMapFilter->SetInput(labelMapFilter->GetOutput());

  StatisticsLabelMapFilterType::Pointer statisticsLabelMapFilter = StatisticsLabelMapFilterType::New();
  statisticsLabelMapFilter->SetInput1(shapeLabelMapFilter->GetOutput());
  statisticsLabelMapFilter->SetInput2(reader->GetOutput());

  statisticsLabelMapFilter->Update();

  RadiometricLabelMapFilterType::Pointer radiometricLabelMapFilter = RadiometricLabelMapFilterType::New();
  radiometricLabelMapFilter->SetInput1(statisticsLabelMapFilter->GetOutput());
  radiometricLabelMapFilter->SetInput2(vreader->GetOutput());
  //radiometricLabelMapFilter->SetReducedAttributeSet(false);
  radiometricLabelMapFilter->SetRedChannelIndex(1);
  radiometricLabelMapFilter->SetNIRChannelIndex(2);
  radiometricLabelMapFilter->Update();

  OpeningLabelMapFilterType::Pointer opening = OpeningLabelMapFilterType::New();
  opening->SetInput(radiometricLabelMapFilter->GetOutput());
  opening->SetAttributeName(attr);
  opening->SetReverseOrdering(lowerThan);
  opening->SetLambda(thresh);

  LabelMapToLabeledImageFilterType::Pointer labelMap2LabeledImage = LabelMapToLabeledImageFilterType::New();
  labelMap2LabeledImage->SetInput(opening->GetOutput());

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outfname);
  writer->SetInput(labelMap2LabeledImage->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/** @file test out VecVertices visitor
 */
#ifdef __WITH_PCL // PCL support required for these tests

#include "core/visitors/visitorvertices.h"

#include "core/exception.h"
#include "ts/ts.h"

using namespace std;
using namespace cv;
using namespace sem;

namespace {

/**
 * @brief test class around VisitorVecVertices
 */
class VisitorVecVerticesTest : public ::testing::Test
{
protected:
    virtual void SetUp()
    {
        to_.Reset();
    }

    VisitorVecVertices to_;    ///< test object
};

TEST_F(VisitorVecVerticesTest, EmptyVecVertices)
{
    EXPECT_TRUE(to_(VecVertices()).empty());
}

TEST_F(VisitorVecVerticesTest, EmptyVecVertices_Size)
{
    EXPECT_SIZE(0, to_(VecVertices()));
}

template<class T>
class VisitorVecVerticesTypedTest : public VisitorVecVerticesTest
{
protected:
    virtual void SetUp()
    {
        to_.Reset();
    }

    //typedef std::list<T> List;
     static T shared_;
     T value_;
};

/**
 * @brief Value per type to use in fixtures below.
 */
template<class T>
struct Twos_
{
    static const T val;
};

///< Register static variables to work with inside tests
template<> const float Twos_<float>::val   = 2.f;
template<> const int Twos_<int>::val     = 2;
template<> const uchar Twos_<uchar>::val   = 2;
template<> const Mat1f Twos_<Mat1f>::val   = Mat1f(1, 1, 2.f);

typedef ::testing::Types<Mat1f, float, int, uchar> VisitorTypes;
TYPED_TEST_CASE(VisitorVecVerticesTypedTest, VisitorTypes);

TYPED_TEST(VisitorVecVerticesTypedTest, Twos)
{
    TypeParam in = Twos_<TypeParam >::val;

    VecVertices vv = to_(in);

    EXPECT_SIZE(1, vv);
    EXPECT_SIZE(1, vv[0].vertices);

    EXPECT_EQ(static_cast<uint32_t>(2), vv[0].vertices[0]);
}

} // annonymous namespace for VecVertices visitors' test fixtures

#else // __WITH_PCL
    #warning "Skipping building VecVertices visitor unit tests due to no pcl support."
#endif // __WITH_PCL
<commit_msg>add test similar to scalars to cover cloud<commit_after>/** @file test out VecVertices visitor
 */
#ifdef __WITH_PCL // PCL support required for these tests

#include "core/visitors/visitorvertices.h"

#include "core/exception.h"
#include "ts/ts.h"

using namespace std;
using namespace cv;
using namespace sem;

namespace {

/**
 * @brief test class around VisitorVecVertices
 */
class VisitorVecVerticesTest : public ::testing::Test
{
protected:
    virtual void SetUp()
    {
        to_.Reset();
    }

    VisitorVecVertices to_;    ///< test object
};

TEST_F(VisitorVecVerticesTest, EmptyVecVertices)
{
    EXPECT_TRUE(to_(VecVertices()).empty());
}

TEST_F(VisitorVecVerticesTest, EmptyVecVertices_Size)
{
    EXPECT_SIZE(0, to_(VecVertices()));
}

TEST_F(VisitorVecVerticesTest, Twos_cloud)
{
    CloudXYZ::Ptr in = Mat2PointCloud(Mat1f(4, 3, 2));

    VecVertices vv = to_(in);

    EXPECT_SIZE(4, vv);
    EXPECT_SIZE(4, vv[0].vertices);

    for(uint32_t i=0; i<in->height; i++) {
        for(uint32_t j=0; j<in->width; j++) {

            EXPECT_EQ(static_cast<uint32_t>(2), vv[i].vertices[j]);
        }
    }
}

template<class T>
class VisitorVecVerticesTypedTest : public VisitorVecVerticesTest
{
protected:
    virtual void SetUp()
    {
        to_.Reset();
    }

    //typedef std::list<T> List;
     static T shared_;
     T value_;
};

/**
 * @brief Value per type to use in fixtures below.
 */
template<class T>
struct Twos_
{
    static const T val;
};

///< Register static variables to work with inside tests
template<> const float Twos_<float>::val    = 2.f;
template<> const int Twos_<int>::val        = 2;
template<> const uchar Twos_<uchar>::val    = 2;
template<> const Mat1f Twos_<Mat1f>::val    = Mat1f(1, 1, 2.f);

typedef ::testing::Types<Mat1f, float, int, uchar> VisitorTypes;
TYPED_TEST_CASE(VisitorVecVerticesTypedTest, VisitorTypes);

TYPED_TEST(VisitorVecVerticesTypedTest, Twos)
{
    TypeParam in = Twos_<TypeParam >::val;

    VecVertices vv = to_(in);

    EXPECT_SIZE(1, vv);
    EXPECT_SIZE(1, vv[0].vertices);

    EXPECT_EQ(static_cast<uint32_t>(2), vv[0].vertices[0]);
}

} // annonymous namespace for VecVertices visitors' test fixtures

#else // __WITH_PCL
    #warning "Skipping building VecVertices visitor unit tests due to no pcl support."
#endif // __WITH_PCL
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of dirtsand.                                             *
 *                                                                            *
 * dirtsand is free software: you can redistribute it and/or modify           *
 * it under the terms of the GNU General Public License as published by       *
 * the Free Software Foundation, either version 3 of the License, or          *
 * (at your option) any later version.                                        *
 *                                                                            *
 * dirtsand is distributed in the hope that it will be useful,                *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
 * GNU General Public License for more details.                               *
 *                                                                            *
 * You should have received a copy of the GNU General Public License          *
 * along with dirtsand.  If not, see <http://www.gnu.org/licenses/>.          *
 ******************************************************************************/

#include "GameServer_Private.h"
#include "settings.h"
#include "errors.h"
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>

extern bool s_commdebug;

#define START_REPLY(msgId) \
    client.m_buffer.truncate(); \
    client.m_buffer.write<uint16_t>(msgId)

#define SEND_REPLY() \
    DS::CryptSendBuffer(client.m_sock, client.m_crypt, \
                        client.m_buffer.buffer(), client.m_buffer.size())

void game_client_init(GameClient_Private& client)
{
    /* Game client header:  size, account uuid, age instance uuid */
    uint32_t size = DS::RecvValue<uint32_t>(client.m_sock);
    DS_PASSERT(size == 36);
    DS::Uuid clientUuid, connUuid;
    DS::RecvBuffer(client.m_sock, clientUuid.m_bytes, sizeof(clientUuid.m_bytes));
    DS::RecvBuffer(client.m_sock, connUuid.m_bytes, sizeof(connUuid.m_bytes));

    /* Establish encryption */
    uint8_t msgId = DS::RecvValue<uint8_t>(client.m_sock);
    DS_PASSERT(msgId == DS::e_CliToServConnect);
    uint8_t msgSize = DS::RecvValue<uint8_t>(client.m_sock);
    DS_PASSERT(msgSize == 66);

    uint8_t Y[64];
    DS::RecvBuffer(client.m_sock, Y, 64);
    BYTE_SWAP_BUFFER(Y, 64);

    uint8_t serverSeed[7];
    uint8_t sharedKey[7];
    DS::CryptEstablish(serverSeed, sharedKey, DS::Settings::CryptKey(DS::e_KeyGame_N),
                       DS::Settings::CryptKey(DS::e_KeyGame_K), Y);

    client.m_buffer.truncate();
    client.m_buffer.write<uint8_t>(DS::e_ServToCliEncrypt);
    client.m_buffer.write<uint8_t>(9);
    client.m_buffer.writeBytes(serverSeed, 7);
    DS::SendBuffer(client.m_sock, client.m_buffer.buffer(), client.m_buffer.size());

    client.m_crypt = DS::CryptStateInit(sharedKey, 7);
}

GameHost_Private* find_game_host(uint32_t ageMcpId)
{
    pthread_mutex_lock(&s_gameHostMutex);
    hostmap_t::iterator host_iter = s_gameHosts.find(ageMcpId);
    GameHost_Private* host = 0;
    if (host_iter != s_gameHosts.end())
        host = host_iter->second;
    pthread_mutex_unlock(&s_gameHostMutex);
    return host ? host : start_game_host(ageMcpId);
}

void cb_ping(GameClient_Private& client)
{
    START_REPLY(e_GameToCli_PingReply);

    // Ping time
    client.m_buffer.write<uint32_t>(DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt));

    SEND_REPLY();
}

void cb_join(GameClient_Private& client)
{
    START_REPLY(e_GameToCli_JoinAgeReply);

    // Trans ID
    client.m_buffer.write<uint32_t>(DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt));

    uint32_t mcpId = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt);
    client.m_host = find_game_host(mcpId);
    DS_PASSERT(client.m_host != 0);

    Game_ClientMessage msg;
    msg.m_client = &client;
    DS::CryptRecvBuffer(client.m_sock, client.m_crypt, client.m_clientId.m_bytes,
                        sizeof(client.m_clientId.m_bytes));
    client.m_clientInfo.set_PlayerId(DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt));
    if (client.m_clientInfo.m_PlayerId == 0) {
        client.m_buffer.write<uint32_t>(DS::e_NetInvalidParameter);
        SEND_REPLY();
        return;
    }

    // Get player info from the vault
    Auth_NodeInfo nodeInfo;
    nodeInfo.m_client = &client;
    nodeInfo.m_node.set_NodeIdx(client.m_clientInfo.m_PlayerId);
    s_authChannel.putMessage(e_VaultFetchNode, reinterpret_cast<void*>(&nodeInfo));

    DS::FifoMessage reply = client.m_channel.getMessage();
    if (reply.m_messageType != DS::e_NetSuccess) {
        client.m_buffer.write<uint32_t>(reply.m_messageType);
        SEND_REPLY();
        return;
    }
    msg.m_client->m_clientInfo.set_PlayerName(nodeInfo.m_node.m_IString64_1);
    msg.m_client->m_clientInfo.set_CCRLevel(0);
    client.m_host->m_channel.putMessage(e_GameJoinAge, reinterpret_cast<void*>(&msg));

    reply = client.m_channel.getMessage();
    client.m_buffer.write<uint32_t>(reply.m_messageType);

    SEND_REPLY();

    pthread_mutex_lock(&client.m_host->m_clientMutex);
    client.m_host->m_clients[client.m_clientInfo.m_PlayerId] = &client;
    pthread_mutex_unlock(&client.m_host->m_clientMutex);
}

void cb_netmsg(GameClient_Private& client)
{
    Game_PropagateMessage msg;
    msg.m_client = &client;
    msg.m_messageType = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt);

    uint32_t size = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt);
    uint8_t* buffer = new uint8_t[size];
    DS::CryptRecvBuffer(client.m_sock, client.m_crypt, buffer, size);
    msg.m_message = DS::Blob::Steal(buffer, size);
    client.m_host->m_channel.putMessage(e_GamePropagate, reinterpret_cast<void*>(&msg));
    client.m_channel.getMessage();
}

void cb_gameMgrMsg(GameClient_Private& client)
{
    uint32_t size = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt);
    uint8_t* buffer = new uint8_t[size];
    DS::CryptRecvBuffer(client.m_sock, client.m_crypt, buffer, size);

    printf("GAME MGR MSG");
    for (size_t i=0; i<size; ++i) {
        if ((i % 16) == 0)
            printf("\n    ");
        else if ((i % 16) == 8)
            printf("   ");
        printf("%02X ", buffer[i]);
    }
    printf("\n");
    delete[] buffer;
}

void* wk_gameWorker(void* sockp)
{
    GameClient_Private client;
    client.m_sock = reinterpret_cast<DS::SocketHandle>(sockp);
    client.m_host = 0;

    try {
        game_client_init(client);
    } catch (DS::AssertException ex) {
        fprintf(stderr, "[Game] Assertion failed at %s:%ld:  %s\n",
                ex.m_file, ex.m_line, ex.m_cond);
        return 0;
    } catch (DS::SockHup) {
        // Socket closed...
        return 0;
    }

    try {
        for ( ;; ) {
            uint16_t msgId = DS::CryptRecvValue<uint16_t>(client.m_sock, client.m_crypt);
            switch (msgId) {
            case e_CliToGame_PingRequest:
                cb_ping(client);
                break;
            case e_CliToGame_JoinAgeRequest:
                cb_join(client);
                break;
            case e_CliToGame_Propagatebuffer:
                DS_PASSERT(client.m_host != 0);
                cb_netmsg(client);
                break;
            case e_CliToGame_GameMgrMsg:
                DS_PASSERT(client.m_host != 0);
                cb_gameMgrMsg(client);
                break;
            default:
                /* Invalid message */
                fprintf(stderr, "[Game] Got invalid message ID %d from %s\n",
                        msgId, DS::SockIpAddress(client.m_sock).c_str());
                DS::CloseSock(client.m_sock);
                throw DS::SockHup();
            }
        }
    } catch (DS::AssertException ex) {
        fprintf(stderr, "[Game] Assertion failed at %s:%ld:  %s\n",
                ex.m_file, ex.m_line, ex.m_cond);
    } catch (DS::SockHup) {
        // Socket closed...
    }

    pthread_mutex_lock(&client.m_host->m_clientMutex);
    client.m_host->m_clients.erase(client.m_clientInfo.m_PlayerId);
    pthread_mutex_unlock(&client.m_host->m_clientMutex);
    Game_ClientMessage msg;
    msg.m_client = &client;
    client.m_host->m_channel.putMessage(e_GameDisconnect, reinterpret_cast<void*>(&msg));
    client.m_channel.getMessage();

    DS::CryptStateFree(client.m_crypt);
    DS::FreeSock(client.m_sock);
    return 0;
}

static int sel_age(const dirent* de)
{
    return strcmp(strrchr(de->d_name, '.'), ".age") == 0;
}

Game_AgeInfo age_parse(FILE* stream)
{
    char lnbuffer[4096];

    Game_AgeInfo age;
    while (fgets(lnbuffer, 4096, stream)) {
        std::vector<DS::String> line = DS::String(lnbuffer).strip('#').split('=');
        if (line.size() == 0)
            continue;
        if (line.size() != 2) {
            fprintf(stderr, "[Game] Invalid AGE line: %s", lnbuffer);
            continue;
        }
        if (line[0] == "StartDateTime") {
            age.m_startTime = line[1].toUint(10);
        } else if (line[0] == "DayLength") {
            age.m_dayLength = line[1].toDouble();
        } else if (line[0] == "MaxCapacity") {
            age.m_maxCapacity = line[1].toUint(10);
        } else if (line[0] == "LingerTime") {
            age.m_lingerTime = line[1].toUint(10);
        } else if (line[0] == "SequencePrefix") {
            age.m_seqPrefix = line[1].toInt(10);
        } else if (line[0] == "ReleaseVersion" || line[0] == "Page") {
            // Ignored
        } else {
            fprintf(stderr, "[Game] Invalid AGE line: %s", lnbuffer);
        }
    }
    return age;
}

void DS::GameServer_Init()
{
    dirent** dirls;
    int count = scandir(DS::Settings::AgePath(), &dirls, &sel_age, &alphasort);
    if (count < 0) {
        fprintf(stderr, "[Game] Error reading age descriptors: %s\n", strerror(errno));
    } else if (count == 0) {
        fprintf(stderr, "[Game] Warning: No age descriptors found!\n");
        free(dirls);
    } else {
        for (int i=0; i<count; ++i) {
            DS::String filename = DS::String::Format("%s/%s", DS::Settings::AgePath(), dirls[i]->d_name);
            FILE* ageFile = fopen(filename.c_str(), "r");
            if (ageFile) {
                char magic[12];
                fread(magic, 1, 12, ageFile);
                if (memcmp(magic, "whatdoyousee", 12) == 0 || memcmp(magic, "notthedroids", 12) == 0
                    || memcmp(magic, "BriceIsSmart", 12) == 0) {
                    fprintf(stderr, "[Game] Error: Please decrypt your .age files before using!\n");
                    break;
                }
                fseek(ageFile, 0, SEEK_SET);

                DS::String ageName = dirls[i]->d_name;
                ageName = ageName.left(ageName.find(".age"));
                Game_AgeInfo age = age_parse(ageFile);
                if (age.m_seqPrefix >= 0)
                    s_ages[ageName] = age;
                fclose(ageFile);
            }
            free(dirls[i]);
        }
        free(dirls);
    }

    pthread_mutex_init(&s_gameHostMutex, 0);
}

void DS::GameServer_Add(DS::SocketHandle client)
{
#ifdef DEBUG
    if (s_commdebug)
        printf("Connecting GAME on %s\n", DS::SockIpAddress(client).c_str());
#endif

    pthread_t threadh;
    pthread_create(&threadh, 0, &wk_gameWorker, reinterpret_cast<void*>(client));
    pthread_detach(threadh);
}

void DS::GameServer_Shutdown()
{
    pthread_mutex_lock(&s_gameHostMutex);
    hostmap_t::iterator host_iter;
    for (host_iter = s_gameHosts.begin(); host_iter != s_gameHosts.end(); ++host_iter)
        host_iter->second->m_channel.putMessage(e_GameShutdown);
    pthread_mutex_unlock(&s_gameHostMutex);

    bool complete = false;
    for (int i=0; i<50 && !complete; ++i) {
        pthread_mutex_lock(&s_gameHostMutex);
        size_t alive = s_gameHosts.size();
        pthread_mutex_unlock(&s_gameHostMutex);
        if (alive == 0)
            complete = true;
        usleep(100000);
    }
    if (!complete)
        fprintf(stderr, "[Game] Servers didn't die after 5 seconds!\n");
    pthread_mutex_destroy(&s_gameHostMutex);
}

void DS::GameServer_DisplayClients()
{
    pthread_mutex_lock(&s_gameHostMutex);
    if (s_gameHosts.size())
        printf("Game Servers:\n");
    for (hostmap_t::iterator host_iter = s_gameHosts.begin();
         host_iter != s_gameHosts.end(); ++host_iter) {
        printf("    {%s}\n", host_iter->second->m_instanceId.toString().c_str());
        std::tr1::unordered_map<uint32_t, GameClient_Private*>::iterator client_iter;
        for (client_iter = host_iter->second->m_clients.begin();
             client_iter != host_iter->second->m_clients.end(); ++ client_iter)
            printf("      * %s - %s (%u)\n", DS::SockIpAddress(client_iter->second->m_sock).c_str(),
                   client_iter->second->m_clientInfo.m_PlayerName.c_str(),
                   client_iter->second->m_clientInfo.m_PlayerId);
    }
    pthread_mutex_unlock(&s_gameHostMutex);
}
<commit_msg>Don't try to remove a client from the host if we're not connected to one.<commit_after>/******************************************************************************
 * This file is part of dirtsand.                                             *
 *                                                                            *
 * dirtsand is free software: you can redistribute it and/or modify           *
 * it under the terms of the GNU General Public License as published by       *
 * the Free Software Foundation, either version 3 of the License, or          *
 * (at your option) any later version.                                        *
 *                                                                            *
 * dirtsand is distributed in the hope that it will be useful,                *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
 * GNU General Public License for more details.                               *
 *                                                                            *
 * You should have received a copy of the GNU General Public License          *
 * along with dirtsand.  If not, see <http://www.gnu.org/licenses/>.          *
 ******************************************************************************/

#include "GameServer_Private.h"
#include "settings.h"
#include "errors.h"
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>

extern bool s_commdebug;

#define START_REPLY(msgId) \
    client.m_buffer.truncate(); \
    client.m_buffer.write<uint16_t>(msgId)

#define SEND_REPLY() \
    DS::CryptSendBuffer(client.m_sock, client.m_crypt, \
                        client.m_buffer.buffer(), client.m_buffer.size())

void game_client_init(GameClient_Private& client)
{
    /* Game client header:  size, account uuid, age instance uuid */
    uint32_t size = DS::RecvValue<uint32_t>(client.m_sock);
    DS_PASSERT(size == 36);
    DS::Uuid clientUuid, connUuid;
    DS::RecvBuffer(client.m_sock, clientUuid.m_bytes, sizeof(clientUuid.m_bytes));
    DS::RecvBuffer(client.m_sock, connUuid.m_bytes, sizeof(connUuid.m_bytes));

    /* Establish encryption */
    uint8_t msgId = DS::RecvValue<uint8_t>(client.m_sock);
    DS_PASSERT(msgId == DS::e_CliToServConnect);
    uint8_t msgSize = DS::RecvValue<uint8_t>(client.m_sock);
    DS_PASSERT(msgSize == 66);

    uint8_t Y[64];
    DS::RecvBuffer(client.m_sock, Y, 64);
    BYTE_SWAP_BUFFER(Y, 64);

    uint8_t serverSeed[7];
    uint8_t sharedKey[7];
    DS::CryptEstablish(serverSeed, sharedKey, DS::Settings::CryptKey(DS::e_KeyGame_N),
                       DS::Settings::CryptKey(DS::e_KeyGame_K), Y);

    client.m_buffer.truncate();
    client.m_buffer.write<uint8_t>(DS::e_ServToCliEncrypt);
    client.m_buffer.write<uint8_t>(9);
    client.m_buffer.writeBytes(serverSeed, 7);
    DS::SendBuffer(client.m_sock, client.m_buffer.buffer(), client.m_buffer.size());

    client.m_crypt = DS::CryptStateInit(sharedKey, 7);
}

GameHost_Private* find_game_host(uint32_t ageMcpId)
{
    pthread_mutex_lock(&s_gameHostMutex);
    hostmap_t::iterator host_iter = s_gameHosts.find(ageMcpId);
    GameHost_Private* host = 0;
    if (host_iter != s_gameHosts.end())
        host = host_iter->second;
    pthread_mutex_unlock(&s_gameHostMutex);
    return host ? host : start_game_host(ageMcpId);
}

void cb_ping(GameClient_Private& client)
{
    START_REPLY(e_GameToCli_PingReply);

    // Ping time
    client.m_buffer.write<uint32_t>(DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt));

    SEND_REPLY();
}

void cb_join(GameClient_Private& client)
{
    START_REPLY(e_GameToCli_JoinAgeReply);

    // Trans ID
    client.m_buffer.write<uint32_t>(DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt));

    uint32_t mcpId = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt);
    client.m_host = find_game_host(mcpId);
    DS_PASSERT(client.m_host != 0);

    Game_ClientMessage msg;
    msg.m_client = &client;
    DS::CryptRecvBuffer(client.m_sock, client.m_crypt, client.m_clientId.m_bytes,
                        sizeof(client.m_clientId.m_bytes));
    client.m_clientInfo.set_PlayerId(DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt));
    if (client.m_clientInfo.m_PlayerId == 0) {
        client.m_buffer.write<uint32_t>(DS::e_NetInvalidParameter);
        SEND_REPLY();
        return;
    }

    // Get player info from the vault
    Auth_NodeInfo nodeInfo;
    nodeInfo.m_client = &client;
    nodeInfo.m_node.set_NodeIdx(client.m_clientInfo.m_PlayerId);
    s_authChannel.putMessage(e_VaultFetchNode, reinterpret_cast<void*>(&nodeInfo));

    DS::FifoMessage reply = client.m_channel.getMessage();
    if (reply.m_messageType != DS::e_NetSuccess) {
        client.m_buffer.write<uint32_t>(reply.m_messageType);
        SEND_REPLY();
        return;
    }
    msg.m_client->m_clientInfo.set_PlayerName(nodeInfo.m_node.m_IString64_1);
    msg.m_client->m_clientInfo.set_CCRLevel(0);
    client.m_host->m_channel.putMessage(e_GameJoinAge, reinterpret_cast<void*>(&msg));

    reply = client.m_channel.getMessage();
    client.m_buffer.write<uint32_t>(reply.m_messageType);

    SEND_REPLY();

    pthread_mutex_lock(&client.m_host->m_clientMutex);
    client.m_host->m_clients[client.m_clientInfo.m_PlayerId] = &client;
    pthread_mutex_unlock(&client.m_host->m_clientMutex);
}

void cb_netmsg(GameClient_Private& client)
{
    Game_PropagateMessage msg;
    msg.m_client = &client;
    msg.m_messageType = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt);

    uint32_t size = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt);
    uint8_t* buffer = new uint8_t[size];
    DS::CryptRecvBuffer(client.m_sock, client.m_crypt, buffer, size);
    msg.m_message = DS::Blob::Steal(buffer, size);
    client.m_host->m_channel.putMessage(e_GamePropagate, reinterpret_cast<void*>(&msg));
    client.m_channel.getMessage();
}

void cb_gameMgrMsg(GameClient_Private& client)
{
    uint32_t size = DS::CryptRecvValue<uint32_t>(client.m_sock, client.m_crypt);
    uint8_t* buffer = new uint8_t[size];
    DS::CryptRecvBuffer(client.m_sock, client.m_crypt, buffer, size);

    printf("GAME MGR MSG");
    for (size_t i=0; i<size; ++i) {
        if ((i % 16) == 0)
            printf("\n    ");
        else if ((i % 16) == 8)
            printf("   ");
        printf("%02X ", buffer[i]);
    }
    printf("\n");
    delete[] buffer;
}

void* wk_gameWorker(void* sockp)
{
    GameClient_Private client;
    client.m_sock = reinterpret_cast<DS::SocketHandle>(sockp);
    client.m_host = 0;

    try {
        game_client_init(client);
    } catch (DS::AssertException ex) {
        fprintf(stderr, "[Game] Assertion failed at %s:%ld:  %s\n",
                ex.m_file, ex.m_line, ex.m_cond);
        return 0;
    } catch (DS::SockHup) {
        // Socket closed...
        return 0;
    }

    try {
        for ( ;; ) {
            uint16_t msgId = DS::CryptRecvValue<uint16_t>(client.m_sock, client.m_crypt);
            switch (msgId) {
            case e_CliToGame_PingRequest:
                cb_ping(client);
                break;
            case e_CliToGame_JoinAgeRequest:
                cb_join(client);
                break;
            case e_CliToGame_Propagatebuffer:
                DS_PASSERT(client.m_host != 0);
                cb_netmsg(client);
                break;
            case e_CliToGame_GameMgrMsg:
                DS_PASSERT(client.m_host != 0);
                cb_gameMgrMsg(client);
                break;
            default:
                /* Invalid message */
                fprintf(stderr, "[Game] Got invalid message ID %d from %s\n",
                        msgId, DS::SockIpAddress(client.m_sock).c_str());
                DS::CloseSock(client.m_sock);
                throw DS::SockHup();
            }
        }
    } catch (DS::AssertException ex) {
        fprintf(stderr, "[Game] Assertion failed at %s:%ld:  %s\n",
                ex.m_file, ex.m_line, ex.m_cond);
    } catch (DS::SockHup) {
        // Socket closed...
    }

    if (client.m_host) {
        pthread_mutex_lock(&client.m_host->m_clientMutex);
        client.m_host->m_clients.erase(client.m_clientInfo.m_PlayerId);
        pthread_mutex_unlock(&client.m_host->m_clientMutex);
        Game_ClientMessage msg;
        msg.m_client = &client;
        client.m_host->m_channel.putMessage(e_GameDisconnect, reinterpret_cast<void*>(&msg));
        client.m_channel.getMessage();
    }

    DS::CryptStateFree(client.m_crypt);
    DS::FreeSock(client.m_sock);
    return 0;
}

static int sel_age(const dirent* de)
{
    return strcmp(strrchr(de->d_name, '.'), ".age") == 0;
}

Game_AgeInfo age_parse(FILE* stream)
{
    char lnbuffer[4096];

    Game_AgeInfo age;
    while (fgets(lnbuffer, 4096, stream)) {
        std::vector<DS::String> line = DS::String(lnbuffer).strip('#').split('=');
        if (line.size() == 0)
            continue;
        if (line.size() != 2) {
            fprintf(stderr, "[Game] Invalid AGE line: %s", lnbuffer);
            continue;
        }
        if (line[0] == "StartDateTime") {
            age.m_startTime = line[1].toUint(10);
        } else if (line[0] == "DayLength") {
            age.m_dayLength = line[1].toDouble();
        } else if (line[0] == "MaxCapacity") {
            age.m_maxCapacity = line[1].toUint(10);
        } else if (line[0] == "LingerTime") {
            age.m_lingerTime = line[1].toUint(10);
        } else if (line[0] == "SequencePrefix") {
            age.m_seqPrefix = line[1].toInt(10);
        } else if (line[0] == "ReleaseVersion" || line[0] == "Page") {
            // Ignored
        } else {
            fprintf(stderr, "[Game] Invalid AGE line: %s", lnbuffer);
        }
    }
    return age;
}

void DS::GameServer_Init()
{
    dirent** dirls;
    int count = scandir(DS::Settings::AgePath(), &dirls, &sel_age, &alphasort);
    if (count < 0) {
        fprintf(stderr, "[Game] Error reading age descriptors: %s\n", strerror(errno));
    } else if (count == 0) {
        fprintf(stderr, "[Game] Warning: No age descriptors found!\n");
        free(dirls);
    } else {
        for (int i=0; i<count; ++i) {
            DS::String filename = DS::String::Format("%s/%s", DS::Settings::AgePath(), dirls[i]->d_name);
            FILE* ageFile = fopen(filename.c_str(), "r");
            if (ageFile) {
                char magic[12];
                fread(magic, 1, 12, ageFile);
                if (memcmp(magic, "whatdoyousee", 12) == 0 || memcmp(magic, "notthedroids", 12) == 0
                    || memcmp(magic, "BriceIsSmart", 12) == 0) {
                    fprintf(stderr, "[Game] Error: Please decrypt your .age files before using!\n");
                    break;
                }
                fseek(ageFile, 0, SEEK_SET);

                DS::String ageName = dirls[i]->d_name;
                ageName = ageName.left(ageName.find(".age"));
                Game_AgeInfo age = age_parse(ageFile);
                if (age.m_seqPrefix >= 0)
                    s_ages[ageName] = age;
                fclose(ageFile);
            }
            free(dirls[i]);
        }
        free(dirls);
    }

    pthread_mutex_init(&s_gameHostMutex, 0);
}

void DS::GameServer_Add(DS::SocketHandle client)
{
#ifdef DEBUG
    if (s_commdebug)
        printf("Connecting GAME on %s\n", DS::SockIpAddress(client).c_str());
#endif

    pthread_t threadh;
    pthread_create(&threadh, 0, &wk_gameWorker, reinterpret_cast<void*>(client));
    pthread_detach(threadh);
}

void DS::GameServer_Shutdown()
{
    pthread_mutex_lock(&s_gameHostMutex);
    hostmap_t::iterator host_iter;
    for (host_iter = s_gameHosts.begin(); host_iter != s_gameHosts.end(); ++host_iter)
        host_iter->second->m_channel.putMessage(e_GameShutdown);
    pthread_mutex_unlock(&s_gameHostMutex);

    bool complete = false;
    for (int i=0; i<50 && !complete; ++i) {
        pthread_mutex_lock(&s_gameHostMutex);
        size_t alive = s_gameHosts.size();
        pthread_mutex_unlock(&s_gameHostMutex);
        if (alive == 0)
            complete = true;
        usleep(100000);
    }
    if (!complete)
        fprintf(stderr, "[Game] Servers didn't die after 5 seconds!\n");
    pthread_mutex_destroy(&s_gameHostMutex);
}

void DS::GameServer_DisplayClients()
{
    pthread_mutex_lock(&s_gameHostMutex);
    if (s_gameHosts.size())
        printf("Game Servers:\n");
    for (hostmap_t::iterator host_iter = s_gameHosts.begin();
         host_iter != s_gameHosts.end(); ++host_iter) {
        printf("    {%s}\n", host_iter->second->m_instanceId.toString().c_str());
        std::tr1::unordered_map<uint32_t, GameClient_Private*>::iterator client_iter;
        for (client_iter = host_iter->second->m_clients.begin();
             client_iter != host_iter->second->m_clients.end(); ++ client_iter)
            printf("      * %s - %s (%u)\n", DS::SockIpAddress(client_iter->second->m_sock).c_str(),
                   client_iter->second->m_clientInfo.m_PlayerName.c_str(),
                   client_iter->second->m_clientInfo.m_PlayerId);
    }
    pthread_mutex_unlock(&s_gameHostMutex);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// An example based on solving matrices based on a 1D hydrogen molecule.
#include <math.h>
#include <mpi.h>
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
#include <vector>
using std::vector;
#include <iostream>
// NTPoly Headers
#include "DensityMatrixSolvers.h"
#include "PSMatrix.h"
#include "ProcessGrid.h"
#include "SolverParameters.h"
#include "Triplet.h"
#include "TripletList.h"
// ETC
const double x_start = -6.28;
const double x_end = 6.28;

////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
  // Input Parameters
  string density_file_out;
  int process_rows, process_columns, process_slices;
  double threshold, convergence_threshold;
  int number_of_electrons;
  int grid_points;

  // Setup MPI
  int provided;
  MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &provided);
  int total_processors;
  MPI_Comm_size(MPI_COMM_WORLD, &total_processors);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  // Process The Input Parameters
  string key, value;
  for (int i = 1; i < argc; i += 2) {
    key = string(argv[i]);
    value = string(argv[i + 1]);
    stringstream ss;
    ss << value;
    if (key == "--density") {
      ss >> density_file_out;
    } else if (key == "--process_rows") {
      ss >> process_rows;
    } else if (key == "--process_columns") {
      ss >> process_columns;
    } else if (key == "--process_slices") {
      ss >> process_slices;
    } else if (key == "--grid_points") {
      ss >> grid_points;
    } else if (key == "--number_of_electrons") {
      ss >> number_of_electrons;
    } else if (key == "--threshold") {
      ss >> threshold;
    } else if (key == "--convergence_threshold") {
      ss >> convergence_threshold;
    }
  }

  // Setup the process grid.
  NTPoly::ConstructProcessGrid(MPI_COMM_WORLD, process_rows, process_columns,
                               process_slices, true);
  // Set Up The Solver Parameters.
  NTPoly::SolverParameters solver_parameters;
  solver_parameters.SetConvergeDiff(convergence_threshold);
  solver_parameters.SetThreshold(threshold);
  solver_parameters.SetVerbosity(true);

  // Divide The Work Amongst Processors.
  int local_grid_points = grid_points / total_processors;
  int start_row = local_grid_points * rank;
  // Handle the edge case
  if (rank == total_processors - 1) {
    local_grid_points = grid_points - rank * local_grid_points;
  }
  vector<double> local_rows(local_grid_points);
  for (int i = 0; i < local_grid_points; ++i) {
    local_rows[i] = start_row + i;
  }

  // Construct A Linear Space.
  vector<double> x_values(local_grid_points);
  double grid_spacing = (x_end - x_start) / (grid_points - 1);
  double local_x_start = x_start + start_row * grid_spacing;
  for (int i = 0; i < local_grid_points; ++i) {
    x_values[i] = local_x_start + i * grid_spacing;
  }

  // Construct The Kinetic Energy Operator.
  NTPoly::TripletList_r triplet_list;
  NTPoly::Triplet_r temp_value;
  for (int counter = 0; counter < local_grid_points; ++counter) {
    temp_value.index_row = start_row + counter + 1;
    // Stencil Point 1
    if (temp_value.index_row > 2) {
      temp_value.index_column = temp_value.index_row - 2;
      temp_value.point_value =
          (-0.5) * (-1.0 / (12.0 * grid_spacing * grid_spacing));
      triplet_list.Append(temp_value);
    }
    // Stencil Point 2
    if (temp_value.index_row > 1) {
      temp_value.index_column = temp_value.index_row - 1;
      temp_value.point_value =
          (-0.5) * (16.0 / (12.0 * grid_spacing * grid_spacing));
      triplet_list.Append(temp_value);
    }
    // Stencil Point 3
    temp_value.index_column = temp_value.index_row;
    temp_value.point_value =
        (-0.5) * (-30.0 / (12.0 * grid_spacing * grid_spacing));
    triplet_list.Append(temp_value);
    // Stencil Point 4
    if (temp_value.index_row + 1 < grid_points) {
      temp_value.index_column = temp_value.index_row + 1;
      temp_value.point_value =
          (-0.5) * (16.0 / (12.0 * grid_spacing * grid_spacing));
      triplet_list.Append(temp_value);
    }
    // Stencil Point 5
    if (temp_value.index_row + 2 < grid_points) {
      temp_value.index_column = temp_value.index_row + 2;
      temp_value.point_value =
          (-0.5) * (-1.0 / (12.0 * grid_spacing * grid_spacing));
      triplet_list.Append(temp_value);
    }
  }
  NTPoly::Matrix_ps KineticEnergy(grid_points);
  KineticEnergy.FillFromTripletList(triplet_list);

  // Construct The Potential Energy Operator.
  NTPoly::TripletList_r potential_triplet_list;
  for (int i = 0; i < local_grid_points; ++i) {
    temp_value.index_row = start_row + i + 1;
    temp_value.index_column = start_row + i + 1;
    temp_value.point_value = -1.0 / fabs(x_values[i]);
    potential_triplet_list.Append(temp_value);
  }
  NTPoly::Matrix_ps PotentialEnergy(grid_points);
  PotentialEnergy.FillFromTripletList(potential_triplet_list);

  // Construct The Full Hamiltonian.
  NTPoly::Matrix_ps Hamiltonian(KineticEnergy);
  Hamiltonian.Increment(PotentialEnergy);

  // Overlap Matrix is just the identity.
  NTPoly::Matrix_ps Identity(grid_points);
  Identity.FillIdentity();

  // Call the solver routine.
  NTPoly::Matrix_ps Density(grid_points);
  double chemical_potential;
  NTPoly::DensityMatrixSolvers::TRS2(Hamiltonian, Identity, 2, Density, energy
                                     chemical_potential, solver_parameters);

  // Print the density matrix to file.
  Density.WriteToMatrixMarket(density_file_out);

  // Cleanup
  NTPoly::DestructProcessGrid();
  MPI_Finalize();
  return 0;
}
<commit_msg>Correction to last merge<commit_after>////////////////////////////////////////////////////////////////////////////////
// An example based on solving matrices based on a 1D hydrogen molecule.
#include <math.h>
#include <mpi.h>
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
#include <vector>
using std::vector;
#include <iostream>
// NTPoly Headers
#include "DensityMatrixSolvers.h"
#include "PSMatrix.h"
#include "ProcessGrid.h"
#include "SolverParameters.h"
#include "Triplet.h"
#include "TripletList.h"
// ETC
const double x_start = -6.28;
const double x_end = 6.28;

////////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
  // Input Parameters
  string density_file_out;
  int process_rows, process_columns, process_slices;
  double threshold, convergence_threshold;
  int number_of_electrons;
  int grid_points;

  // Setup MPI
  int provided;
  MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &provided);
  int total_processors;
  MPI_Comm_size(MPI_COMM_WORLD, &total_processors);
  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  // Process The Input Parameters
  string key, value;
  for (int i = 1; i < argc; i += 2) {
    key = string(argv[i]);
    value = string(argv[i + 1]);
    stringstream ss;
    ss << value;
    if (key == "--density") {
      ss >> density_file_out;
    } else if (key == "--process_rows") {
      ss >> process_rows;
    } else if (key == "--process_columns") {
      ss >> process_columns;
    } else if (key == "--process_slices") {
      ss >> process_slices;
    } else if (key == "--grid_points") {
      ss >> grid_points;
    } else if (key == "--number_of_electrons") {
      ss >> number_of_electrons;
    } else if (key == "--threshold") {
      ss >> threshold;
    } else if (key == "--convergence_threshold") {
      ss >> convergence_threshold;
    }
  }

  // Setup the process grid.
  NTPoly::ConstructProcessGrid(MPI_COMM_WORLD, process_rows, process_columns,
                               process_slices, true);
  // Set Up The Solver Parameters.
  NTPoly::SolverParameters solver_parameters;
  solver_parameters.SetConvergeDiff(convergence_threshold);
  solver_parameters.SetThreshold(threshold);
  solver_parameters.SetVerbosity(true);

  // Divide The Work Amongst Processors.
  int local_grid_points = grid_points / total_processors;
  int start_row = local_grid_points * rank;
  // Handle the edge case
  if (rank == total_processors - 1) {
    local_grid_points = grid_points - rank * local_grid_points;
  }
  vector<double> local_rows(local_grid_points);
  for (int i = 0; i < local_grid_points; ++i) {
    local_rows[i] = start_row + i;
  }

  // Construct A Linear Space.
  vector<double> x_values(local_grid_points);
  double grid_spacing = (x_end - x_start) / (grid_points - 1);
  double local_x_start = x_start + start_row * grid_spacing;
  for (int i = 0; i < local_grid_points; ++i) {
    x_values[i] = local_x_start + i * grid_spacing;
  }

  // Construct The Kinetic Energy Operator.
  NTPoly::TripletList_r triplet_list;
  NTPoly::Triplet_r temp_value;
  for (int counter = 0; counter < local_grid_points; ++counter) {
    temp_value.index_row = start_row + counter + 1;
    // Stencil Point 1
    if (temp_value.index_row > 2) {
      temp_value.index_column = temp_value.index_row - 2;
      temp_value.point_value =
          (-0.5) * (-1.0 / (12.0 * grid_spacing * grid_spacing));
      triplet_list.Append(temp_value);
    }
    // Stencil Point 2
    if (temp_value.index_row > 1) {
      temp_value.index_column = temp_value.index_row - 1;
      temp_value.point_value =
          (-0.5) * (16.0 / (12.0 * grid_spacing * grid_spacing));
      triplet_list.Append(temp_value);
    }
    // Stencil Point 3
    temp_value.index_column = temp_value.index_row;
    temp_value.point_value =
        (-0.5) * (-30.0 / (12.0 * grid_spacing * grid_spacing));
    triplet_list.Append(temp_value);
    // Stencil Point 4
    if (temp_value.index_row + 1 < grid_points) {
      temp_value.index_column = temp_value.index_row + 1;
      temp_value.point_value =
          (-0.5) * (16.0 / (12.0 * grid_spacing * grid_spacing));
      triplet_list.Append(temp_value);
    }
    // Stencil Point 5
    if (temp_value.index_row + 2 < grid_points) {
      temp_value.index_column = temp_value.index_row + 2;
      temp_value.point_value =
          (-0.5) * (-1.0 / (12.0 * grid_spacing * grid_spacing));
      triplet_list.Append(temp_value);
    }
  }
  NTPoly::Matrix_ps KineticEnergy(grid_points);
  KineticEnergy.FillFromTripletList(triplet_list);

  // Construct The Potential Energy Operator.
  NTPoly::TripletList_r potential_triplet_list;
  for (int i = 0; i < local_grid_points; ++i) {
    temp_value.index_row = start_row + i + 1;
    temp_value.index_column = start_row + i + 1;
    temp_value.point_value = -1.0 / fabs(x_values[i]);
    potential_triplet_list.Append(temp_value);
  }
  NTPoly::Matrix_ps PotentialEnergy(grid_points);
  PotentialEnergy.FillFromTripletList(potential_triplet_list);

  // Construct The Full Hamiltonian.
  NTPoly::Matrix_ps Hamiltonian(KineticEnergy);
  Hamiltonian.Increment(PotentialEnergy);

  // Overlap Matrix is just the identity.
  NTPoly::Matrix_ps Identity(grid_points);
  Identity.FillIdentity();

  // Call the solver routine.
  NTPoly::Matrix_ps Density(grid_points);
  double chemical_potential, energy;
  NTPoly::DensityMatrixSolvers::TRS2(Hamiltonian, Identity, 2, Density, energy
                                     chemical_potential, solver_parameters);

  // Print the density matrix to file.
  Density.WriteToMatrixMarket(density_file_out);

  // Cleanup
  NTPoly::DestructProcessGrid();
  MPI_Finalize();
  return 0;
}
<|endoftext|>