leocad/common/pieceinf.cpp

378 lines
9.8 KiB
C++
Raw Normal View History

#include "lc_global.h"
2012-03-29 03:10:55 +02:00
#include "lc_math.h"
2012-04-14 01:41:58 +02:00
#include "lc_mesh.h"
#include "lc_colors.h"
2012-10-12 01:55:55 +02:00
#include "lc_texture.h"
2011-09-07 23:06:51 +02:00
#include "opengl.h"
#include "pieceinf.h"
2012-10-02 03:23:44 +02:00
#include "lc_library.h"
2011-09-07 23:06:51 +02:00
#include "lc_application.h"
2014-12-24 16:52:52 +01:00
#include "lc_model.h"
#include "lc_context.h"
#include "camera.h"
2015-04-05 01:52:20 +02:00
#include <locale.h>
2011-09-07 23:06:51 +02:00
PieceInfo::PieceInfo()
2011-09-07 23:06:51 +02:00
{
mZipFileType = LC_NUM_ZIPFILES;
mZipFileIndex = -1;
mFlags = 0;
2012-10-12 01:55:55 +02:00
mRefCount = 0;
mMesh = NULL;
2014-12-24 16:52:52 +01:00
mModel = NULL;
2011-09-07 23:06:51 +02:00
}
2012-04-14 01:41:58 +02:00
PieceInfo::~PieceInfo()
2011-09-07 23:06:51 +02:00
{
2012-10-12 02:21:04 +02:00
if (mRefCount)
Unload();
2011-09-07 23:06:51 +02:00
}
2014-12-26 18:09:11 +01:00
QString PieceInfo::GetSaveID() const
{
if (mFlags & LC_PIECE_MODEL)
return QString::fromLatin1(m_strName);
2014-12-26 18:09:11 +01:00
return QString::fromLatin1(m_strName) + QLatin1String(".DAT");
}
void PieceInfo::SetPlaceholder()
{
m_fDimensions[0] = 10.0f;
m_fDimensions[1] = 10.0f;
m_fDimensions[2] = 4.0f;
m_fDimensions[3] = -10.0f;
m_fDimensions[4] = -10.0f;
m_fDimensions[5] = -24.0f;
mFlags = LC_PIECE_PLACEHOLDER | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES;
mModel = NULL;
delete mMesh;
mMesh = NULL;
}
void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh)
2014-12-24 16:52:52 +01:00
{
if (mModel != Model)
{
mFlags = LC_PIECE_MODEL;
mModel = Model;
}
2014-12-24 16:52:52 +01:00
strncpy(m_strName, Model->GetProperties().mName.toUpper().toLatin1().data(), sizeof(m_strName));
m_strName[sizeof(m_strName)-1] = 0;
strncpy(m_strDescription, Model->GetProperties().mName.toLatin1().data(), sizeof(m_strDescription));
m_strDescription[sizeof(m_strDescription)-1] = 0;
2015-03-21 21:12:04 +01:00
const QStringList& MeshLines = Model->GetFileLines();
if (UpdateMesh && !MeshLines.isEmpty())
{
lcMemFile PieceFile;
foreach (const QString& Line, MeshLines)
{
QByteArray Buffer = Line.toLatin1();
PieceFile.WriteBuffer(Buffer.constData(), Buffer.size());
PieceFile.WriteBuffer("\r\n", 2);
}
lcLibraryMeshData MeshData;
lcArray<lcLibraryTextureMap> TextureStack;
PieceFile.Seek(0, SEEK_SET);
const char* OldLocale = setlocale(LC_NUMERIC, "C");
bool Ret = lcGetPiecesLibrary()->ReadMeshData(PieceFile, lcMatrix44Identity(), 16, TextureStack, MeshData);
setlocale(LC_NUMERIC, OldLocale);
if (Ret)
lcGetPiecesLibrary()->CreateMesh(this, MeshData);
}
2014-12-24 16:52:52 +01:00
}
bool PieceInfo::IncludesModel(const lcModel* Model) const
{
if (mFlags & LC_PIECE_MODEL)
{
if (mModel == Model)
return true;
return mModel->IncludesModel(Model);
}
return false;
}
void PieceInfo::CreatePlaceholder(const char* Name)
{
strncpy(m_strName, Name, sizeof(m_strName));
m_strName[sizeof(m_strName)-1] = 0;
strncpy(m_strDescription, Name, sizeof(m_strDescription));
m_strDescription[sizeof(m_strDescription)-1] = 0;
SetPlaceholder();
}
2012-10-12 01:55:55 +02:00
void PieceInfo::Load()
2011-09-07 23:06:51 +02:00
{
if (mFlags & LC_PIECE_MODEL)
return;
else if (mFlags & LC_PIECE_PLACEHOLDER)
mFlags |= LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES;
2012-10-02 03:23:44 +02:00
else
lcGetPiecesLibrary()->LoadPiece(this);
2014-09-11 21:55:34 +02:00
}
2011-09-07 23:06:51 +02:00
2012-10-12 01:55:55 +02:00
void PieceInfo::Unload()
2011-09-07 23:06:51 +02:00
{
2014-12-24 16:52:52 +01:00
if (mMesh)
2012-10-12 01:55:55 +02:00
{
2014-12-24 16:52:52 +01:00
for (int SectionIdx = 0; SectionIdx < mMesh->mNumSections; SectionIdx++)
{
lcMeshSection& Section = mMesh->mSections[SectionIdx];
2012-10-12 01:55:55 +02:00
2014-12-24 16:52:52 +01:00
if (Section.Texture)
Section.Texture->Release();
}
2012-10-12 01:55:55 +02:00
2014-12-24 16:52:52 +01:00
delete mMesh;
mMesh = NULL;
}
mModel = NULL;
2015-02-22 03:39:15 +01:00
if (IsModel())
lcGetPiecesLibrary()->RemovePiece(this);
2011-09-07 23:06:51 +02:00
}
2014-12-26 16:44:46 +01:00
bool PieceInfo::MinIntersectDist(const lcMatrix44& WorldMatrix, const lcVector3& WorldStart, const lcVector3& WorldEnd, float& MinDistance) const
{
lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(WorldMatrix);
lcVector3 Start = lcMul31(WorldStart, InverseWorldMatrix);
lcVector3 End = lcMul31(WorldEnd, InverseWorldMatrix);
lcVector3 Min(m_fDimensions[3], m_fDimensions[4], m_fDimensions[5]);
lcVector3 Max(m_fDimensions[0], m_fDimensions[1], m_fDimensions[2]);
float Distance;
if (!lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, NULL) || (Distance >= MinDistance))
return false;
if (mFlags & LC_PIECE_PLACEHOLDER)
return true;
bool Intersect = false;
2014-12-26 16:44:46 +01:00
if (mMesh)
{
lcVector3 Intersection;
Intersect = mMesh->MinIntersectDist(Start, End, MinDistance, Intersection);
}
if (mFlags & LC_PIECE_MODEL)
Intersect |= mModel->SubModelMinIntersectDist(Start, End, MinDistance);
return Intersect;
2014-12-26 16:44:46 +01:00
}
bool PieceInfo::BoxTest(const lcMatrix44& WorldMatrix, const lcVector4 WorldPlanes[6]) const
{
lcMatrix44 InverseWorldMatrix = lcMatrix44AffineInverse(WorldMatrix);
const int NumCorners = 8;
const int NumPlanes = 6;
lcVector4 LocalPlanes[NumPlanes];
for (int PlaneIdx = 0; PlaneIdx < NumPlanes; PlaneIdx++)
{
lcVector3 PlaneNormal = lcMul30(WorldPlanes[PlaneIdx], InverseWorldMatrix);
LocalPlanes[PlaneIdx] = lcVector4(PlaneNormal, WorldPlanes[PlaneIdx][3] - lcDot3(InverseWorldMatrix[3], PlaneNormal));
}
lcVector3 Box[NumCorners] =
{
lcVector3(m_fDimensions[0], m_fDimensions[1], m_fDimensions[5]),
lcVector3(m_fDimensions[3], m_fDimensions[1], m_fDimensions[5]),
lcVector3(m_fDimensions[0], m_fDimensions[1], m_fDimensions[2]),
lcVector3(m_fDimensions[3], m_fDimensions[4], m_fDimensions[5]),
lcVector3(m_fDimensions[3], m_fDimensions[4], m_fDimensions[2]),
lcVector3(m_fDimensions[0], m_fDimensions[4], m_fDimensions[2]),
lcVector3(m_fDimensions[0], m_fDimensions[4], m_fDimensions[5]),
lcVector3(m_fDimensions[3], m_fDimensions[1], m_fDimensions[2])
};
int Outcodes[NumCorners];
for (int CornerIdx = 0; CornerIdx < NumCorners; CornerIdx++)
{
Outcodes[CornerIdx] = 0;
for (int PlaneIdx = 0; PlaneIdx < NumPlanes; PlaneIdx++)
{
if (lcDot3(Box[CornerIdx], LocalPlanes[PlaneIdx]) + LocalPlanes[PlaneIdx][3] > 0)
Outcodes[CornerIdx] |= 1 << PlaneIdx;
}
}
int OutcodesOR = 0, OutcodesAND = 0x3f;
for (int CornerIdx = 0; CornerIdx < NumCorners; CornerIdx++)
{
OutcodesAND &= Outcodes[CornerIdx];
OutcodesOR |= Outcodes[CornerIdx];
}
if (OutcodesAND != 0)
return false;
if (OutcodesOR == 0)
return true;
if (mFlags & LC_PIECE_PLACEHOLDER)
return gPlaceholderMesh->IntersectsPlanes(LocalPlanes);
if (mMesh && mMesh->IntersectsPlanes(LocalPlanes))
return true;
if (mFlags & LC_PIECE_MODEL)
return mModel->SubModelBoxTest(LocalPlanes);
return false;
2014-12-26 16:44:46 +01:00
}
2011-09-07 23:06:51 +02:00
// Zoom extents for the preview window and print catalog
void PieceInfo::ZoomExtents(const lcMatrix44& ProjectionMatrix, lcMatrix44& ViewMatrix, float* EyePos) const
2011-09-07 23:06:51 +02:00
{
2012-06-21 02:41:53 +02:00
lcVector3 Points[8] =
2011-09-07 23:06:51 +02:00
{
2012-06-21 02:41:53 +02:00
lcVector3(m_fDimensions[0], m_fDimensions[1], m_fDimensions[5]),
lcVector3(m_fDimensions[3], m_fDimensions[1], m_fDimensions[5]),
lcVector3(m_fDimensions[0], m_fDimensions[1], m_fDimensions[2]),
lcVector3(m_fDimensions[3], m_fDimensions[4], m_fDimensions[5]),
lcVector3(m_fDimensions[3], m_fDimensions[4], m_fDimensions[2]),
lcVector3(m_fDimensions[0], m_fDimensions[4], m_fDimensions[2]),
lcVector3(m_fDimensions[0], m_fDimensions[4], m_fDimensions[5]),
lcVector3(m_fDimensions[3], m_fDimensions[1], m_fDimensions[2])
};
2011-09-07 23:06:51 +02:00
2012-06-21 02:41:53 +02:00
lcVector3 Center(GetCenter());
lcVector3 Position;
2011-09-07 23:06:51 +02:00
2012-06-21 02:41:53 +02:00
if (EyePos)
Position = lcVector3(EyePos[0], EyePos[1], EyePos[2]);
else
2014-08-30 21:48:36 +02:00
Position = lcVector3(-250.0f, -250.0f, 75.0f);
2012-06-21 02:41:53 +02:00
Position += Center;
2011-09-07 23:06:51 +02:00
2012-06-21 02:41:53 +02:00
lcMatrix44 ModelView = lcMatrix44LookAt(Position, Center, lcVector3(0, 0, 1));
Position = lcZoomExtents(Position, ModelView, ProjectionMatrix, Points, 8);
ViewMatrix = lcMatrix44LookAt(Position, Center, lcVector3(0, 0, 1));
2011-09-07 23:06:51 +02:00
if (EyePos)
{
2012-06-21 02:41:53 +02:00
EyePos[0] = Position[0];
EyePos[1] = Position[1];
EyePos[2] = Position[2];
2011-09-07 23:06:51 +02:00
}
}
void PieceInfo::AddRenderMesh(lcScene& Scene)
2014-12-24 16:52:52 +01:00
{
if (!mMesh)
2014-12-24 16:52:52 +01:00
return;
lcRenderMesh RenderMesh;
RenderMesh.WorldMatrix = lcMatrix44Identity();
RenderMesh.Mesh = mMesh;
RenderMesh.ColorIndex = gDefaultColor;
RenderMesh.Focused = false;
RenderMesh.Selected = false;
2014-12-24 16:52:52 +01:00
if (mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES))
2015-02-08 19:54:51 +01:00
Scene.mOpaqueMeshes.Add(RenderMesh);
2014-12-24 16:52:52 +01:00
if (mFlags & LC_PIECE_HAS_TRANSLUCENT)
2014-12-24 16:52:52 +01:00
{
RenderMesh.Distance = Scene.mViewMatrix.r[3].z;
2014-12-24 16:52:52 +01:00
2015-02-08 19:54:51 +01:00
Scene.mTranslucentMeshes.Add(RenderMesh);
2014-04-23 16:53:43 +02:00
}
}
2014-12-30 17:30:12 +01:00
void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int ColorIndex, bool Focused, bool Selected)
{
if (mMesh || (mFlags & LC_PIECE_PLACEHOLDER))
{
lcRenderMesh RenderMesh;
RenderMesh.WorldMatrix = WorldMatrix;
RenderMesh.Mesh = (mFlags & LC_PIECE_PLACEHOLDER) ? gPlaceholderMesh : mMesh;
RenderMesh.ColorIndex = ColorIndex;
RenderMesh.Focused = Focused;
RenderMesh.Selected = Selected;
bool Translucent = lcIsColorTranslucent(ColorIndex);
if ((mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent))
Scene.mOpaqueMeshes.Add(RenderMesh);
if ((mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
{
lcVector3 Pos = lcMul31(WorldMatrix[3], Scene.mViewMatrix);
RenderMesh.Distance = Pos[2];
Scene.mTranslucentMeshes.Add(RenderMesh);
}
}
if (mFlags & LC_PIECE_MODEL)
mModel->SubModelAddRenderMeshes(Scene, WorldMatrix, ColorIndex, Focused, Selected);
}
2014-12-30 17:30:12 +01:00
void PieceInfo::GetPartsList(int DefaultColorIndex, lcArray<lcPartsListEntry>& PartsList) const
{
if (mFlags & LC_PIECE_MODEL)
{
mModel->GetPartsList(DefaultColorIndex, PartsList);
return;
}
for (int UsedIdx = 0; UsedIdx < PartsList.GetSize(); UsedIdx++)
{
if (PartsList[UsedIdx].Info != this || PartsList[UsedIdx].ColorIndex != DefaultColorIndex)
continue;
PartsList[UsedIdx].Count++;
return;
}
lcPartsListEntry& PartsListEntry = PartsList.Add();
PartsListEntry.Info = const_cast<PieceInfo*>(this);
PartsListEntry.ColorIndex = DefaultColorIndex;
PartsListEntry.Count = 1;
}
void PieceInfo::GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcArray<lcModelPartsEntry>& ModelParts) const
{
if (mFlags & LC_PIECE_MODEL)
{
mModel->GetModelParts(WorldMatrix, DefaultColorIndex, ModelParts);
return;
}
lcModelPartsEntry& ModelPartsEntry = ModelParts.Add();
ModelPartsEntry.WorldMatrix = WorldMatrix;
ModelPartsEntry.ColorIndex = DefaultColorIndex;
ModelPartsEntry.Info = const_cast<PieceInfo*>(this);
}
void PieceInfo::UpdateBoundingBox(lcArray<lcModel*>& UpdatedModels)
{
if (mFlags & LC_PIECE_MODEL)
mModel->UpdatePieceInfo(UpdatedModels);
}