Show kmap.cpp syntax highlighted
/*
Copyright (C) 2003, 2004, 2005 by Luca Cappa
Written by Luca Cappa groton@users.sourceforge.net
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//all the wall are tall 220cm and 10cm wide.
//all the meshes are oriented to (0,0,1) by default.
#include "cssysdef.h"
#include "csutil/sysfunc.h"
#include "iutil/vfs.h"
#include "csutil/cscolor.h"
#include "csutil/scfstr.h"
#include "cstool/csview.h"
#include "cstool/initapp.h"
#include "iutil/eventq.h"
#include "iutil/event.h"
#include "iutil/objreg.h"
#include "iutil/csinput.h"
#include "iutil/virtclk.h"
#include "iengine/sector.h"
#include "iengine/engine.h"
#include "iengine/camera.h"
#include "iengine/light.h"
#include "iengine/texture.h"
#include "iengine/mesh.h"
#include "iengine/movable.h"
#include "iengine/material.h"
#include "imesh/thing.h"
#include "imesh/object.h"
#include "imesh/sprite3d.h"
#include "ivideo/graph3d.h"
#include "ivideo/graph2d.h"
#include "ivideo/natwin.h"
#include "ivideo/txtmgr.h"
#include "ivideo/texture.h"
#include "ivideo/material.h"
#include "ivideo/fontserv.h"
#include "igraphic/imageio.h"
#include "imap/loader.h"
#include "ivaria/reporter.h"
#include "ivaria/stdrep.h"
#include "ivaria/conout.h"
#include "ivaria/collider.h"
#include "csutil/cmdhelp.h"
#include "csutil/cspmeter.h"
#include "csutil/xmltiny.h"
#include "csutil/csstring.h"
#include "csutil/cmdhelp.h"
#include "csgeom/quaterni.h"
#include "csgeom/transfrm.h"
#include "igeom/polymesh.h"
#include "igeom/objmodel.h"
#include "cstool/collider.h"
#include "iaws/aws.h"
#include "iaws/awscnvs.h"
#include "isense/iisensetracker.h"
#include "korientation.h"
#include "kblockid.h"
#include "kblock.h"
#include "kflags.h"
#include "kterrain.h"
#include "ske.h"
#include "kutil.h"
#include "klightlist.h"
#include "klight.h"
//Include for this file.
#include "kmap.h"
//------------------ Cell ------------------------
const Cell Cell::mInvalid = Cell (true);
void Cell::Reset ()
{
delete m_block;
m_block = 0;
m_orientation = KOrientation::INVALID;
this->mInvalidFlag = false;
}
//--------------- KMap ----------------------------
SCF_IMPLEMENT_IBASE (KMap)
SCF_IMPLEMENTS_INTERFACE (iKXMLWriter)
SCF_IMPLEMENTS_INTERFACE (iKXMLReader)
SCF_IMPLEMENT_IBASE_END
//new
KMap::KMap (iSector* p_sector)
{
SCF_CONSTRUCT_IBASE (0);
m_g3d = CS_QUERY_REGISTRY (g_objReg, iGraphics3D);
m_engine = CS_QUERY_REGISTRY (g_objReg, iEngine);
m_collideSystem = CS_QUERY_REGISTRY (g_objReg, iCollideSystem);
m_loader = CS_QUERY_REGISTRY (g_objReg, iLoader);
m_sector = p_sector;
m_Xsize = 0;
m_Zsize = 0;
m_name = 0;
//
//Load some default materials and set them.
if (!m_loader->LoadTexture ("floor", "/SKE/texture/floor.jpg"))
{
SKE::Report (CS_REPORTER_SEVERITY_WARNING,
"Error loading 'floor' texture!");
}//if
if (!m_loader->LoadTexture ("floor2", "/SKE/texture/floor2.jpg"))
{
SKE::Report (CS_REPORTER_SEVERITY_WARNING,
"Error loading 'floor2' texture!");
}//if
if (!m_loader->LoadTexture ("wall", "/SKE/texture/wall.bmp"))
{
SKE::Report (CS_REPORTER_SEVERITY_WARNING,
"Error loading 'wall' texture!");
}//if
if (!m_loader->LoadTexture ("wall2", "/SKE/texture/wall2.bmp"))
{
SKE::Report (CS_REPORTER_SEVERITY_WARNING,
"Error loading 'wall2' texture!");
}//if
SetMaterial (m_engine->GetMaterialList ()->FindByName ("wall2"),
m_engine->GetMaterialList ()->FindByName ("floor2"));
//
//Reset the flags.
GetFlags ().SetAll (0);
//
//Create the list of lights.
m_lightList.AttachNew (new KLightList ());
}
//????const KMap& KMap::operator= (const KMap& p_map)
KMap::~KMap ()
{
DestroyCells ();
SCF_DESTRUCT_IBASE ();
}
csFlags& KMap::GetFlags ()
{
return m_flags;
}
void KMap::DestroyCells ()
{
/* size_t l_i, l_j;
for (l_i = 0; l_i < m_Xsize; l_i++)
{
for(l_j = 0; l_j < m_Zsize; l_j++)
RemoveBlock (l_i, l_j);
}//for*/
//Delete all the Cells.
csArray<csArray<Cell> >::Iterator lIt = m_map.GetIterator ();
while (lIt.HasNext ())
{
((csArray<Cell>&)lIt.Next ()).Empty ();
}//while
m_map.Empty ();
}
/*bool KMap::AddLight (KLight* p_light)
{
}
bool KMap::RemoveLight (KLight* p_light)
{
}
bool KMap::GetLight (char* p_name)
{
}
void KMap::Relight ()
{
}*/
void KMap::GetAt (size_t p_X, size_t p_Z, KBlock*& p_block,
KOrientation& p_or) const
{
//
//Test for boundaries of the map.
if ((p_X < 0) || (p_Z < 0) || (p_X >= m_Xsize) || (p_Z >= m_Zsize))
return;
p_block = m_map[p_X][p_Z].m_block;
p_or = m_map[p_X][p_Z].m_orientation;
}
KBlock* KMap::CreateBlock (const KBlockId& p_bId, const KOrientation& p_o)
{
//
//Create the KBlock.
KBlock* lB = new KBlock ();
lB->Create (p_bId, *m_wallMaterial, *m_floorMaterial);
//Rotate mesh to the right orientation.
RotateBlockY (*lB, p_o);
return lB;
}
bool KMap::PutBlock (const KBlockId& p_bId, size_t p_X, size_t p_Z,
const KOrientation& p_o, bool p_autoRotateEnaled)
{
//
//Test for boundaries of the map.
if ((p_X < 0) || (p_Z < 0) || (p_X >= m_Xsize) || (p_Z >= m_Zsize))
return false;
//
//If there is already a KBlock there destroy it.
KOrientation lOr (p_o);
if (m_map[p_X][p_Z].IsBlock ())
{
//
//Determine the orientation.
//If the same KBlockId is already in the position, rotate the orientation clockwise.
//This autorotation could be disabled by the p_autoRotateEnaled argument set to false.
if (p_autoRotateEnaled && (m_map[p_X][p_Z].m_block->m_blockId == p_bId))
{
lOr = m_map[p_X][p_Z].m_orientation;
lOr = lOr.RotateClockwise ();
}//if
//
m_map[p_X][p_Z].Reset ();
}//if
//
//Create a block and put it in the map.
KBlock* lBlock = CreateBlock (p_bId, lOr);
//
//Translate it in an 'hard' way to the right place.
csMatrix3 l_mat;
csVector3 l_v (p_X, 0, p_Z);
csTransform l_tr (l_mat, l_v);
lBlock->HardTransform (l_tr);
//
//Set in the sector at pos (0,0,0).
lBlock->GetMeshWrapper()->GetMovable()->SetSector (m_sector);
lBlock->GetMeshWrapper()->GetMovable()->SetPosition (csVector3(0, 0, 0));
lBlock->GetMeshWrapper()->GetMovable()->UpdateMove();
//
//Set the name for this KBlock.
scfString lName;
lName.Append( Integer2String (p_X));
lName.Append("_");
lName.Append( Integer2String (p_Z));
lBlock->SetName (lName);
//Rotate properly the flags.
lBlock->m_flag->Rotate (lOr);
m_map[p_X][p_Z].Set (lBlock, lOr);
//
//??Dont use automatic relighting.
//GetFlags ().Set (KMap::KMAP_NEED_RELIGHTING);
return true;
}
void KMap::AttachColliders ()
{
csRef<KBlock> l_b;
size_t i, j;
for (i = 0; i < m_Xsize; i++)
for (j = 0; j < m_Zsize; j++)
{
l_b = m_map[i][j].m_block;
if (l_b->m_blockId == KBlockId::F)
continue;
//
//Create the collider for this KBlock.
csRef<iPolygonMesh> l_polMesh = l_b->GetMeshWrapper()->GetMeshObject ()->
GetObjectModel ()->GetPolygonMeshColldet ();
if (l_polMesh)
{
//
//The ref to the csColliderW is not needed afterward since it is stored
//inside the iObject of iMeshWrapper.
csRef<csColliderWrapper> l_cW = new csColliderWrapper (
l_b->GetMeshWrapper()->QueryObject (), m_collideSystem, l_polMesh);
l_cW->SetName (l_b->GetName ());
}//if
}//for
}
void KMap::DetachColliders ()
{
KBlock* l_b = 0;
size_t i, j;
for (i = 0; i < m_Xsize; i++)
for (j = 0; j < m_Zsize; j++)
{
l_b = m_map[i][j].m_block;
if ((l_b == 0) || (l_b->m_blockId == KBlockId::F))
continue;
//
//Destroy the collider for this KBlock.
csRef<csColliderWrapper> l_cW = CS_GET_CHILD_OBJECT
(l_b->GetMeshWrapper ()->QueryObject (), csColliderWrapper);
CS_ASSERT (l_cW != NULL);
l_b->GetMeshWrapper ()->QueryObject ()->ObjRemove (l_cW);
}//for
}
bool KMap::RemoveBlock (size_t p_indexX, size_t p_indexZ)
{
if( (p_indexZ > m_Zsize) || (p_indexX > m_Xsize) ||
(p_indexZ < 0) || (p_indexX < 0) )
return false;
//
//Destroy the KBlock.
m_map[p_indexX][p_indexZ].Reset ();
//
//??Dont use automatic relighting.
//GetFlags ().Set (KMap::KMAP_NEED_RELIGHTING);
return true;
}
void KMap::RemoveBlock (char* p_name)
{
CS_ASSERT(false);
Cell& lCell = FindBlockByName (p_name);
lCell.Reset ();
//
//??Dont use automatic relighting.
//GetFlags ().Set (KMAP_NEED_RELIGHTING);
}
Cell& KMap::FindBlockByName (const char* p_name)
{
size_t i, j;
for (i = 0; i < m_Xsize; i++)
for (j = 0; j < m_Zsize; j++)
{
if (m_map[i][j].IsBlock ())
if (strcmp (m_map[i][j].m_block->GetName (), p_name))
return m_map[i][j];
}//for
return (Cell&)Cell::mInvalid;//??UGLY!casting away constness.
}
void KMap::RemoveNotVisiblePolygons()
{
/*
//??????????????????????????NOT USED ANYMORE!
int z,x;
for(z = 0; z < m_Zsize; z++)
for(x = 0; x < m_Xsize; x++)
{
KBlock* l_b = m_map[x][z].m_block;
if ( ( l_b == NULL ) ) //|| ( !strcmp(l_b->m_blockId->GetName(),"F") ) )
continue;
iMeshWrapper* l_mW = l_b->GetMeshWrapper();
csRef<iThingState> l_mWS = SCF_QUERY_INTERFACE(l_mW->GetMeshObject(),iThingState);
iPolygon3D* l_polN=NULL;
iPolygon3D* l_polE=NULL;
iPolygon3D* l_polS=NULL;
iPolygon3D* l_polW=NULL;
if (m_map[x][z].m_orientation == KOrientation::NORTH)
{
l_polN=l_mWS->GetPolygon("n");
l_polE=l_mWS->GetPolygon("e");
l_polS=l_mWS->GetPolygon("s");
l_polW=l_mWS->GetPolygon("w");
}
else if (m_map[x][z].m_orientation == KOrientation::EAST)
{
l_polN=l_mWS->GetPolygon("w");
l_polE=l_mWS->GetPolygon("n");
l_polS=l_mWS->GetPolygon("e");
l_polW=l_mWS->GetPolygon("s");
}
else if (m_map[x][z].m_orientation == KOrientation::SOUTH)
{
l_polN=l_mWS->GetPolygon("s");
l_polE=l_mWS->GetPolygon("w");
l_polS=l_mWS->GetPolygon("n");
l_polW=l_mWS->GetPolygon("e");
}
else if (m_map[x][z].m_orientation == KOrientation::WEST)
{
l_polN=l_mWS->GetPolygon("e");
l_polE=l_mWS->GetPolygon("s");
l_polS=l_mWS->GetPolygon("w");
l_polW=l_mWS->GetPolygon("n");
}
if((l_polN!=NULL)&&(z+1<m_Zsize)&&(m_map[x][z+1].m_block!=NULL)&&
(m_map[x][z+1].m_block->m_flag->Compatible(l_b->m_flag,
KOrientation::NORTH)))
{
int l_indexN=l_mWS->FindPolygonIndex(l_polN);
l_mWS->GetFactory ()->RemovePolygon(l_indexN);
}
if((l_polE!=NULL)&&(x+1<m_Xsize)&&(m_map[x+1][z].m_block!=NULL)&&
(m_map[x+1][z].m_block->m_flag->Compatible(l_b->m_flag,
KOrientation::EAST)))
{
int l_indexE=l_mWS->FindPolygonIndex(l_polE);
l_mWS->GetFactory ()->RemovePolygon(l_indexE);
}
if((l_polS!=NULL)&&(z-1>=0)&&(m_map[x][z-1].m_block!=NULL)&&
(m_map[x][z-1].m_block->m_flag->Compatible(l_b->m_flag,
KOrientation::SOUTH)))
{
int l_indexS=l_mWS->FindPolygonIndex(l_polS);
l_mWS->GetFactory ()->RemovePolygon(l_indexS);
}
if((l_polW!=NULL)&&(x-1>=0)&&(m_map[x-1][z].m_block!=NULL)&&
(m_map[x-1][z].m_block->m_flag->Compatible(l_b->m_flag,
KOrientation::WEST)))
{
int l_indexW=l_mWS->FindPolygonIndex(l_polW);
l_mWS->GetFactory ()->RemovePolygon(l_indexW);
}
}//for*/
}
void KMap::Resize (csVector2 const& pNewSize)
{
m_map.SetLength (pNewSize.x, csArray<Cell> ());
size_t i = 0, j = 0;
for (; i < pNewSize.x; i++)
m_map[i].SetLength (pNewSize.y, Cell::mInvalid);
//
//Set the new size.
m_Xsize = pNewSize.x;
m_Zsize = pNewSize.y;
//
//Fill the new Cells created (if any) with a floor oriented to north.
for (i = 0; i < m_Xsize; i++)
{
for (j = 0; j < m_Zsize; j++)
{
Cell& lCell = m_map[i][j];
if (lCell.IsInvalid ())
PutBlock (KBlockId::F, i, j, KOrientation::NORTH, false);
}//for
}//for
//
//??Dont use automatic relighting.
//GetFlags ().Set (KMAP_NEED_RELIGHTING);
}
void KMap::SetSize (csVector2 const& p_v)
{
//
//Set the new size.
m_Xsize = p_v.x;
m_Zsize = p_v.y;
//
//Create internal structures.
size_t l_i, l_j;
m_map.SetLength (m_Xsize);
csArray<csArray<Cell> >::Iterator lIt = m_map.GetIterator ();
while (lIt.HasNext ())
{
((csArray<Cell>&)lIt.Next ()).SetLength (m_Zsize);//?? cast away the constness.
}//while
for (l_i = 0; l_i < m_Xsize; l_i++)
{
for (l_j = 0; l_j < m_Zsize; l_j++)
PutBlock (KBlockId::F, l_i, l_j, KOrientation::NORTH, false);
}//for
//???????
/*g_ske->m_terrain->SetFlatZone (csVector2 (-1, m_Zsize),
csVector2 (m_Xsize, -1));*/
//
//??Dont use automatic relighting.
//GetFlags ().Set (KMAP_NEED_RELIGHTING);
}
csVector2 KMap::GetSize() const
{
return csVector2 (m_Xsize, m_Zsize);
}
bool KMap::SetMaterial (iMaterialWrapper* p_wallMat,
iMaterialWrapper* p_floorMat)
{
m_wallMaterial = p_wallMat;
m_floorMaterial = p_floorMat;
return true;
}
bool SetMaterialForWholeMap (iMaterialWrapper*, iMaterialWrapper*)
{
//????? TO DO!
return true;
}
void KMap::RotateBlockY (KBlock& p_b, const KOrientation& p_orientation)
{
csReversibleTransform l_revTr;
float l_angle = 0.0f;
if (p_orientation == KOrientation::NORTH)
l_angle = 0.0f;
else if (p_orientation == KOrientation::EAST)
l_angle = K_PI2;
else if (p_orientation == KOrientation::SOUTH)
l_angle = K_PI;
else if (p_orientation == KOrientation::WEST)
l_angle = K_3PI2;
l_revTr.RotateThis (csVector3 (0, 1, 0), l_angle);
p_b.HardTransform (l_revTr);
//
//??Dont use automatic relighting.
//GetFlags ().Set (KMAP_NEED_RELIGHTING);
}
/*void KMap::UpdateLights ()
{
iLightList* l_lL = m_sector->GetLights ();
//
//Delete all the current 4 lights in the sector.
int i = l_lL->GetCount () - 1;
for (;i > -1; i--)
l_lL->Remove (i);
//
//Recreate the 4 lights.
int l_influence = m_Xsize > m_Zsize ? m_Xsize : m_Zsize ;
m_lightNW.AttachNew (
m_engine->CreateLight (NULL, csVector3 (-1, l_influence / 2.f, m_Zsize),
l_influence,
csColor (0.6f, 0.6f, 0.6f), false));
l_lL->Add (m_lightNW->QueryLight ());
csRef<iLight> l_l = SCF_QUERY_INTERFACE (m_lightNW, iLight);
l_l->SetAttenuation (CS_ATTN_CLQ);
m_lightNE.AttachNew (
m_engine->CreateLight (NULL, csVector3 (m_Xsize, l_influence / 2.f, m_Zsize),
l_influence,
csColor (0.6f, 0.6f, 0.6f), false));
l_lL->Add (m_lightNE->QueryLight ());
l_l = SCF_QUERY_INTERFACE (m_lightNE, iLight);
l_l->SetAttenuation (CS_ATTN_CLQ);
m_lightSE.AttachNew (
m_engine->CreateLight (NULL, csVector3 (m_Xsize, l_influence / 2.f, -1),
l_influence,
csColor (0.6f, 0.6f, 0.6f), false));
l_lL->Add (m_lightSE->QueryLight ());
l_l = SCF_QUERY_INTERFACE (m_lightSE, iLight);
l_l->SetAttenuation (CS_ATTN_CLQ);
m_lightSW.AttachNew (
m_engine->CreateLight (NULL, csVector3 (-1, l_influence / 2.f, -1),
l_influence,
csColor (0.6f, 0.6f, 0.6f), false));
l_lL->Add (m_lightSW->QueryLight ());
l_l = SCF_QUERY_INTERFACE (m_lightSW, iLight);
l_l->SetAttenuation (CS_ATTN_CLQ);
Relight ();
}*/
//
//
bool KMap::Write (iDocumentNode* p_parent) const
{
csVector2 l_box = GetSize ();
int l_x = l_box.x;
int l_z = l_box.y;
csRef<iDocumentNode> l_levelNode =
p_parent->CreateNodeBefore (CS_NODE_ELEMENT, 0);
l_levelNode->SetValue ("level");
l_levelNode->SetAttribute ("name", m_name ? m_name : "null_NAME");
l_levelNode->SetAttributeAsInt ("xsize", l_x);
l_levelNode->SetAttributeAsInt ("zsize", l_z);
int i,j;
for (i = 0; i < l_x; i++)
{
for (j = 0; j < l_z; j++)
{
KBlock* l_block;
KOrientation l_or;
GetAt (i, j, l_block, l_or);
//create a new KBlock node.
csRef<iDocumentNode> l_blockNode =
l_levelNode->CreateNodeBefore (CS_NODE_ELEMENT, NULL);
l_blockNode->SetValue ("block");
l_blockNode->SetAttribute ("name", l_block->GetName());
l_blockNode->SetAttributeAsInt ("x", i);
l_blockNode->SetAttributeAsInt ("z", j);
l_blockNode->SetAttribute ("orientation", l_or.GetName());
l_blockNode->SetAttribute ("block_id", l_block->m_blockId.GetName());
}//for j
}//for i
//
//Save the lightlist!
m_lightList->Write (l_levelNode);
return true;
}
bool KMap::Read (iDocumentNode* p_parent)
{
const char* l_value = p_parent->GetValue ();
if (strcmpi (l_value, "level"))
return false;
char const* l_name = p_parent->GetAttributeValue ("name");
SetName (l_name);
int l_x = p_parent->GetAttributeValueAsInt ("xsize");
int l_z = p_parent->GetAttributeValueAsInt ("zsize");
SetSize (csVector2 (l_x, l_z));
csRef<iDocumentNodeIterator> l_it = p_parent->GetNodes ();
while (l_it->HasNext ())
{
csRef<iDocumentNode> l_child = l_it->Next ();
if (l_child->GetType () != CS_NODE_ELEMENT)
continue;
const char* l_value = l_child->GetValue ();
if (!strcmpi (l_value, "block"))
{
const char* l_blockName = l_child->GetAttributeValue ("name");
const float l_x = l_child->GetAttributeValueAsFloat ("x");
const float l_z = l_child->GetAttributeValueAsFloat ("z");
const char* l_blockOr = l_child->GetAttributeValue ("orientation");
const char* l_blockId = l_child->GetAttributeValue ("block_id");
//put the KBlock
PutBlock (KBlockId::GetByName (l_blockId), l_x, l_z,
KOrientation::GetByName (l_blockOr), false);
}//if
}//while
//
//Load the lightlist!
csRef<iDocumentNode> l_llist = p_parent->GetNode ("lights_list");//?? UGLY!
if (l_llist)
m_lightList->Read (l_llist);
else
SKE::Report (CS_REPORTER_SEVERITY_NOTIFY,
"There is not a light list for the level called '%s'", GetName ());
return true;
}
void KMap::SetName (const char* p_name)
{
delete [] m_name;
m_name = csStrNew (p_name);
}
const char* KMap::GetName () const
{
return m_name;
}
void KMap::HideLights (bool p_b)
{
//
//Hide the lights!
size_t i;
for (i = 0; i < m_lightList->GetCount (); i++)
m_lightList->Get (i)->SetVisible (false);
}
void KMap::AddLight (KLight* p_light)
{
m_lightList->Add (p_light);
}
void KMap::RemoveLight (KLight* p_light)
{
p_light->UnlinkToMesh ();
m_lightList->Remove (p_light);
}
KLight* KMap::FindLightByName (const char* p_lightName)
{
return m_lightList->FindByName (p_lightName);
}
KLightList const* KMap::GetLightList ()
{
return m_lightList;
}
See more files for this project here