JurassicParkTrespasser/jp2_pc/Source/GUIApp/FindDuplicates.cpp

333 lines
7.3 KiB
C++

/**********************************************************************************************
*
* Copyright © DreamWorks Interactive, 1998
*
* Contents: Implementation of 'FindDuplicates.hpp'
*
**********************************************************************************************
*
* $Log:: /JP2_PC/Source/GUIApp/FindDuplicates.cpp $
*
* 8 98/09/17 16:38 Speter
* Update due to DebugConsole.hpp.
*
* 7 8/30/98 4:52p Asouth
* added default constructor for MW build
*
* 6 8/19/98 1:43p Rwyatt
* Platonic instances are hash based
*
* 5 8/16/98 3:10p Agrant
* Make text out scale relative to master
*
* 4 98.08.13 4:25p Mmouni
* Changes for VC++ 5.0sp3 compatibility.
*
* 3 7/31/98 4:16p Agrant
* only share if you have the same materials, friction, density, etc
*
* 2 7/31/98 3:16p Agrant
* real implementation
*
* 1 7/30/98 5:52p Agrant
* initial rev
*
*********************************************************************************************/
//
// Includes.
//
#include "common.hpp"
#include "Lib/GeomDBase/PartitionPriv.hpp"
#include "Lib/EntityDBase/WorldDBase.hpp"
#include "Lib/EntityDBase/Instance.hpp"
#include "Lib/EntityDBase/PhysicsInfo.hpp"
#include "Lib/GeomDBase/Mesh.hpp"
#include "Lib/Sys/DebugConsole.hpp"
#include "Lib/Loader/PlatonicInstance.hpp"
#include "Game/AI/AIInfo.hpp"
#include "Lib/Physics/InfoBox.hpp"
#include "Lib/Transform/TransformIO.hpp"
#include <fstream>
#include <set>
float fTolerance = 0.01f;
class CDescription {
public:
// default constructor added so MSL can construct the class
CDescription();
CDescription(const CInstance* pins);
const CInstance* pinsBase;
CVector3<> v3Extent;
TSoundMaterial matMaterial;
float fDensity;
float fFriction;
float fElasticity;
bool bPathfind;
bool operator<(const CDescription&) const;
};
extern TMapHashPins tmPlatonicIdeal;
typedef std::set<CDescription, std::less<CDescription> > TSetDescPins;
TSetDescPins tsdpDescriptions;
bool bIsCandidate(const CInstance* pins)
{
const CPhysicsInfo* pphi = pins->pphiGetPhysicsInfo();
// Must have physics info. Must be immovable.
if (!pphi || pphi->bIsMovable() || !pphi->bIsTangible())
return false;
rptr_const<CMesh> pmsh = rptr_const_dynamic_cast(CMesh, pins->prdtGetRenderInfo());
if (!pmsh || pmsh->pampPolygons.uLen == 0)
{
const CBoundVol* pbv = pins->pphiGetPhysicsInfo()->pbvGetBoundVol();
const CBoundVolBox* pbvb = pbv->pbvbCast();
if (pbvb)
{
if (!((CPhysicsInfoBox*)pphi)->v3Pivot.bIsZero())
{
dout << pins->strGetInstanceName() << " --off center pivot point! " << ((CPhysicsInfoBox*)pphi)->v3Pivot << "\n";
return false;
}
return true;
}
}
return false;
}
void FindDuplicates()
{
std::ofstream ofs("Duplicates.txt");
if (!ofs.is_open())
{
// Some sort of failure.
return;
}
// The error allowed in matching boxes.
float f_tolerance = .001;
// First, make a list of all instances.
TMapHashPins::iterator i = tmPlatonicIdeal.begin();
for ( ; i != tmPlatonicIdeal.end(); ++i)
{
const CInstance* pins = (*i).second;
if (pins)
{
// Is it a good candidate?
if (bIsCandidate(pins))
{
// Yes!
std::pair<TSetDescPins::iterator, bool> p = tsdpDescriptions.insert(CDescription(pins));
if (!p.second)
{
// Match!
void DuplicateTextOut(std::ofstream&, const CInstance*, const CInstance*);
DuplicateTextOut(ofs, (*p.first).pinsBase, pins);
}
}
}
}
}
CVector3<> v3MakePositive(CVector3<> v3)
{
v3.tX = abs(v3.tX);
v3.tY = abs(v3.tY);
v3.tZ = abs(v3.tZ);
return v3;
}
bool bVectorsMatch(const CVector3<>& v3_a, const CVector3<>& v3_b)
{
CVector3<> v3_diff = v3_a - v3_b;
return (v3_diff.tLenSqr() < 3 * fTolerance * fTolerance);
}
CRotate3<> r3FindRot(const CVector3<>& v3_master, const CVector3<>& v3_copy)
{
CRotate3<> r3;
// Returns the rotation that takes only 90 degree turns to get from master to copy
if (bVectorsMatch(v3_master, v3_copy)) // XYZ
{
// Natural instance. Just take the copy's presence.
return r3;
}
#define PID2 (0.5 * 3.14159265)
// Jump through hoops.
CRotate3<> r3_x = CRotate3<>(CVector3<>(1,0,0), PID2);
CRotate3<> r3_y = CRotate3<>(CVector3<>(0,1,0), PID2);
CRotate3<> r3_z = CRotate3<>(CVector3<>(0,0,1), PID2);
r3 = r3_x;
CVector3<> v3 = v3_copy * r3; // XZY
v3 = v3MakePositive(v3);
if (bVectorsMatch(v3_master, v3))
{
return r3;
}
r3 = r3 * r3_z;
v3 = v3_copy * r3; // ZXY
v3 = v3MakePositive(v3);
if (bVectorsMatch(v3_master, v3))
{
return r3;
}
r3 = r3 * r3_x;
v3 = v3_copy * r3; // ZYX
v3 = v3MakePositive(v3);
if (bVectorsMatch(v3_master, v3))
{
return r3;
}
r3 = r3 * r3_z;
v3 = v3_copy * r3; // YZX
v3 = v3MakePositive(v3);
if (bVectorsMatch(v3_master, v3))
{
return r3;
}
r3 = r3 * r3_x;
v3 = v3_copy * r3; // YXZ
v3 = v3MakePositive(v3);
if (bVectorsMatch(v3_master, v3))
{
return r3;
}
AlwaysAssert(false);
return r3;
}
void DuplicateTextOut(std::ofstream& ofs, const CInstance* pins_master, const CInstance* pins_copy)
{
// Get the physics infos:
const CPhysicsInfoBox* pphib_master = (CPhysicsInfoBox*)pins_master->pphiGetPhysicsInfo();
const CPhysicsInfoBox* pphib_copy = (CPhysicsInfoBox*)pins_copy->pphiGetPhysicsInfo();
// Assume that the pivot points are centered!
AlwaysAssert(pphib_master->v3Pivot.bIsZero());
AlwaysAssert(pphib_copy->v3Pivot.bIsZero());
// Calculate a presence for the master such that if set, it will exactly coincide with the copy.
CPresence3<> pr3_copy = pins_copy->pr3Presence();
CVector3<> v3_master = pphib_master->bvbBoundVol.v3GetMax();
CVector3<> v3_copy = pphib_copy->bvbBoundVol.v3GetMax();
pr3_copy.r3Rot = pr3_copy.r3Rot * r3FindRot(v3_master, v3_copy);
/// WRITING!
ofs << pins_master->strGetInstanceName() << ' ' << pins_copy->strGetInstanceName();
// Write its placement.
ofs << ' ' << pr3_copy;
ofs << ' ' << pins_copy->fGetScale() / pins_master->fGetScale();
ofs << std::endl;
}
CDescription::CDescription(const CInstance* pins)
{
pinsBase = pins;
const CPhysicsInfoBox* pphib = (CPhysicsInfoBox*)pins->pphiGetPhysicsInfo();
const CBoundVol* pbv = pphib->pbvGetBoundVol();
const CBoundVolBox* pbvb = pbv->pbvbCast();
AlwaysAssert(pbvb);
bPathfind = pins->paiiGetAIInfo()->bPathfinding();
matMaterial = pphib->smatGetMaterialType();
fDensity = pphib->fDensity;
fFriction = pphib->fFriction;
fElasticity = pphib->fElasticity;
// v3Extent should be the physical bounding volume extents, in descending order of magnitude.
CVector3<> v3 = pbvb->v3GetMax();
if (v3.tY < v3.tZ)
{
Swap(v3.tY, v3.tZ);
}
if (v3.tX < v3.tY)
{
Swap(v3.tX, v3.tY);
}
if (v3.tY < v3.tZ)
{
Swap(v3.tY, v3.tZ);
}
v3Extent = v3;
AlwaysAssert(v3.tX >= v3.tY);
AlwaysAssert(v3.tY >= v3.tZ);
AlwaysAssert(v3.tX > 0.99f);
}
bool CDescription::operator<(const CDescription& desc) const
{
float f_low = 1.0 - fTolerance;
if (!bPathfind && desc.bPathfind)
return true;
if (matMaterial < desc.matMaterial)
return true;
if (fDensity < desc.fDensity)
return true;
if (fFriction < desc.fFriction)
return true;
if (fElasticity < desc.fElasticity)
return true;
if (v3Extent.tX < desc.v3Extent.tY * f_low)
return true;
else if (v3Extent.tY < desc.v3Extent.tY * f_low)
return true;
else if (v3Extent.tZ < desc.v3Extent.tZ * f_low)
return true;
else
return false;
}