Support drawing triangles and lines in model files.

This commit is contained in:
leo 2015-02-23 00:50:37 +00:00
parent 7c1d5ae635
commit 4d9288c952
6 changed files with 191 additions and 66 deletions

View file

@ -893,6 +893,16 @@ bool lcPiecesLibrary::LoadPiece(PieceInfo* Info)
return false;
}
CreateMesh(Info, MeshData);
if (mZipFiles[LC_ZIPFILE_OFFICIAL])
mSaveCache = true;
return true;
}
void lcPiecesLibrary::CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData)
{
lcMesh* Mesh = new lcMesh();
int NumIndices = 0;
@ -1011,11 +1021,6 @@ bool lcPiecesLibrary::LoadPiece(PieceInfo* Info)
Mesh->UpdateBuffers();
Info->SetMesh(Mesh);
if (mZipFiles[LC_ZIPFILE_OFFICIAL])
mSaveCache = true;
return true;
}
bool lcPiecesLibrary::LoadTexture(lcTexture* Texture)
@ -1444,19 +1449,15 @@ bool lcPiecesLibrary::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransf
return true;
}
void lcLibraryMeshData::ResequenceQuad(lcVector3* Vertices, int a, int b, int c, int d)
void lcLibraryMeshData::ResequenceQuad(int* Indices, int a, int b, int c, int d)
{
lcVector3 TempVertices[4];
memcpy(TempVertices, Vertices, sizeof(TempVertices));
Vertices[0] = TempVertices[a];
Vertices[1] = TempVertices[b];
Vertices[2] = TempVertices[c];
Vertices[3] = TempVertices[d];
Indices[0] = a;
Indices[1] = b;
Indices[2] = c;
Indices[3] = d;
}
void lcLibraryMeshData::TestQuad(lcVector3* Vertices)
void lcLibraryMeshData::TestQuad(int* QuadIndices, const lcVector3* Vertices)
{
lcVector3 v01 = Vertices[1] - Vertices[0];
lcVector3 v02 = Vertices[2] - Vertices[0];
@ -1474,20 +1475,20 @@ void lcLibraryMeshData::TestQuad(lcVector3* Vertices)
if (lcDot(lcCross(v12, v01), lcCross(v01, v13)) > 0.0f)
{
if (-lcDot(lcCross(v02, v12), lcCross(v12, v23)) > 0.0f)
ResequenceQuad(Vertices, 1, 2, 3, 0);
ResequenceQuad(QuadIndices, 1, 2, 3, 0);
else
ResequenceQuad(Vertices, 0, 3, 1, 2);
ResequenceQuad(QuadIndices, 0, 3, 1, 2);
}
else
{
if (-lcDot(lcCross(v02, v12), lcCross(v12, v23)) > 0.0f)
ResequenceQuad(Vertices, 0, 1, 3, 2);
ResequenceQuad(QuadIndices, 0, 1, 3, 2);
else
ResequenceQuad(Vertices, 1, 2, 3, 0);
ResequenceQuad(QuadIndices, 1, 2, 3, 0);
}
}
void lcLibraryMeshData::AddLine(int LineType, lcuint32 ColorCode, lcVector3* Vertices)
void lcLibraryMeshData::AddLine(int LineType, lcuint32 ColorCode, const lcVector3* Vertices)
{
lcLibraryMeshSection* Section = NULL;
int SectionIdx;
@ -1508,14 +1509,16 @@ void lcLibraryMeshData::AddLine(int LineType, lcuint32 ColorCode, lcVector3* Ver
mSections.Add(Section);
}
int QuadIndices[4] = { 0, 1, 2, 3 };
if (LineType == 4)
TestQuad(Vertices);
TestQuad(QuadIndices, Vertices);
int Indices[4] = { -1, -1, -1, -1 };
for (int IndexIdx = 0; IndexIdx < LineType; IndexIdx++)
{
const lcVector3& Position = Vertices[IndexIdx];
const lcVector3& Position = Vertices[QuadIndices[IndexIdx]];
for (int VertexIdx = mVertices.GetSize() - 1; VertexIdx >= 0; VertexIdx--)
{
@ -1564,7 +1567,7 @@ void lcLibraryMeshData::AddLine(int LineType, lcuint32 ColorCode, lcVector3* Ver
}
}
void lcLibraryMeshData::AddTexturedLine(int LineType, lcuint32 ColorCode, const lcLibraryTextureMap& Map, lcVector3* Vertices)
void lcLibraryMeshData::AddTexturedLine(int LineType, lcuint32 ColorCode, const lcLibraryTextureMap& Map, const lcVector3* Vertices)
{
lcLibraryMeshSection* Section = NULL;
int SectionIdx;
@ -1585,14 +1588,16 @@ void lcLibraryMeshData::AddTexturedLine(int LineType, lcuint32 ColorCode, const
mSections.Add(Section);
}
int QuadIndices[4] = { 0, 1, 2, 3 };
if (LineType == 4)
TestQuad(Vertices);
TestQuad(QuadIndices, Vertices);
int Indices[4] = { -1, -1, -1, -1 };
for (int IndexIdx = 0; IndexIdx < LineType; IndexIdx++)
{
const lcVector3& Position = Vertices[IndexIdx];
const lcVector3& Position = Vertices[QuadIndices[IndexIdx]];
lcVector2 TexCoord(lcDot3(lcVector3(Position.x, Position.y, Position.z), Map.Params[0]) + Map.Params[0].w,
lcDot3(lcVector3(Position.x, Position.y, Position.z), Map.Params[1]) + Map.Params[1].w);

View file

@ -68,12 +68,12 @@ public:
delete mSections[SectionIdx];
}
void AddLine(int LineType, lcuint32 ColorCode, lcVector3* Vertices);
void AddTexturedLine(int LineType, lcuint32 ColorCode, const lcLibraryTextureMap& Map, lcVector3* Vertices);
void AddLine(int LineType, lcuint32 ColorCode, const lcVector3* Vertices);
void AddTexturedLine(int LineType, lcuint32 ColorCode, const lcLibraryTextureMap& Map, const lcVector3* Vertices);
void AddMeshData(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode, lcLibraryTextureMap* TextureMap);
void AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, lcuint32 CurrentColorCode, lcLibraryTextureMap* TextureMap);
void TestQuad(lcVector3* Vertices);
void ResequenceQuad(lcVector3* Vertices, int a, int b, int c, int d);
void TestQuad(int* QuadIndices, const lcVector3* Vertices);
void ResequenceQuad(int* QuadIndices, int a, int b, int c, int d);
lcArray<lcLibraryMeshSection*> mSections;
lcArray<lcVertex> mVertices;
@ -143,6 +143,8 @@ public:
mNumOfficialPieces = mPieces.GetSize();
}
void CreateMesh(PieceInfo* Info, lcLibraryMeshData& MeshData);
lcArray<PieceInfo*> mPieces;
lcArray<lcLibraryPrimitive*> mPrimitives;
int mNumOfficialPieces;

View file

@ -206,12 +206,13 @@ void lcModel::DeleteModel()
mCameras.DeleteAll();
mLights.DeleteAll();
mGroups.DeleteAll();
mMeshLines.RemoveAll();
}
void lcModel::CreatePieceInfo(Project* Project)
{
mPieceInfo = lcGetPiecesLibrary()->FindPiece(mProperties.mName.toUpper().toLatin1().constData(), Project, true);
mPieceInfo->SetModel(this);
mPieceInfo->SetModel(this, true);
mPieceInfo->AddRef();
}
@ -220,10 +221,12 @@ void lcModel::UpdatePieceInfo(lcArray<lcModel*>& UpdatedModels)
if (UpdatedModels.FindIndex(this) != -1)
return;
mPieceInfo->SetModel(this);
mPieceInfo->SetModel(this, false);
UpdatedModels.Add(this);
if (mPieces.IsEmpty())
lcMesh* Mesh = mPieceInfo->GetMesh();
if (mPieces.IsEmpty() && !Mesh)
{
memset(mPieceInfo->m_fDimensions, 0, sizeof(mPieceInfo->m_fDimensions));
return;
@ -242,6 +245,23 @@ void lcModel::UpdatePieceInfo(lcArray<lcModel*>& UpdatedModels)
}
}
if (Mesh)
{
int NumVerts = Mesh->mVertexBuffer.mSize / sizeof(lcVertex);
float* Vertex = (float*)Mesh->mVertexBuffer.mData;
for (int VertexIdx = 0; VertexIdx < NumVerts; VertexIdx++)
{
if (Vertex[0] < BoundingBox[0]) BoundingBox[0] = Vertex[0];
if (Vertex[1] < BoundingBox[1]) BoundingBox[1] = Vertex[1];
if (Vertex[2] < BoundingBox[2]) BoundingBox[2] = Vertex[2];
if (Vertex[0] > BoundingBox[3]) BoundingBox[3] = Vertex[0];
if (Vertex[1] > BoundingBox[4]) BoundingBox[4] = Vertex[1];
if (Vertex[2] > BoundingBox[5]) BoundingBox[5] = Vertex[2];
Vertex += 3;
}
}
mPieceInfo->m_fDimensions[0] = BoundingBox[3];
mPieceInfo->m_fDimensions[1] = BoundingBox[4];
mPieceInfo->m_fDimensions[2] = BoundingBox[5];
@ -486,6 +506,37 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project)
mPieces.Add(Piece);
Piece = NULL;
}
else if (Token == QLatin1String("2"))
{
lcModelMeshLine& Line = mMeshLines.Add();
Line.LineType = 2;
LineStream >> Line.ColorCode;
for (int TokenIdx = 0; TokenIdx < 6; TokenIdx++)
LineStream >> ((float*)Line.Vertices)[TokenIdx];
}
else if (Token == QLatin1String("3"))
{
lcModelMeshLine& Line = mMeshLines.Add();
Line.LineType = 3;
LineStream >> Line.ColorCode;
for (int TokenIdx = 0; TokenIdx < 9; TokenIdx++)
LineStream >> ((float*)Line.Vertices)[TokenIdx];
}
else if (Token == QLatin1String("4"))
{
lcModelMeshLine& Line = mMeshLines.Add();
Line.LineType = 4;
LineStream >> Line.ColorCode;
for (int TokenIdx = 0; TokenIdx < 12; TokenIdx++)
LineStream >> ((float*)Line.Vertices)[TokenIdx];
}
}
mCurrentStep = CurrentStep;
@ -867,6 +918,8 @@ void lcModel::GetScene(lcScene& Scene, lcCamera* ViewCamera, bool DrawInterface)
{
Scene.Begin(ViewCamera->mWorldView);
mPieceInfo->AddRenderMesh(Scene);
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
{
lcPiece* Piece = mPieces[PieceIdx];

View file

@ -113,6 +113,13 @@ struct lcModelPartsEntry
int ColorIndex;
};
struct lcModelMeshLine
{
int LineType;
int ColorCode;
lcVector3 Vertices[4];
};
class lcModel
{
public:
@ -163,6 +170,11 @@ public:
mProperties.mName = Name;
}
const lcArray<lcModelMeshLine>& GetMeshLines() const
{
return mMeshLines;
}
lcStep GetLastStep() const;
lcStep GetCurrentStep() const
@ -333,6 +345,7 @@ protected:
lcArray<lcCamera*> mCameras;
lcArray<lcLight*> mLights;
lcArray<lcGroup*> mGroups;
lcArray<lcModelMeshLine> mMeshLines;
lcModelHistoryEntry* mSavedHistory;
lcArray<lcModelHistoryEntry*> mUndoHistory;

View file

@ -51,18 +51,33 @@ void PieceInfo::SetPlaceholder()
mMesh = NULL;
}
void PieceInfo::SetModel(lcModel* Model)
void PieceInfo::SetModel(lcModel* Model, bool UpdateMesh)
{
mFlags = LC_PIECE_MODEL;
mModel = Model;
if (mModel != Model)
{
mFlags = LC_PIECE_MODEL;
mModel = Model;
}
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;
delete mMesh;
mMesh = NULL;
const lcArray<lcModelMeshLine>& MeshLines = Model->GetMeshLines();
if (UpdateMesh && !MeshLines.IsEmpty())
{
lcLibraryMeshData MeshData;
for (int LineIdx = 0; LineIdx < MeshLines.GetSize(); LineIdx++)
{
const lcModelMeshLine& Line = MeshLines[LineIdx];
MeshData.AddLine(Line.LineType, Line.ColorCode, Line.Vertices);
}
lcGetPiecesLibrary()->CreateMesh(this, MeshData);
}
}
bool PieceInfo::IncludesModel(const lcModel* Model) const
@ -126,9 +141,6 @@ bool PieceInfo::MinIntersectDist(const lcMatrix44& WorldMatrix, const lcVector3&
lcVector3 Start = lcMul31(WorldStart, InverseWorldMatrix);
lcVector3 End = lcMul31(WorldEnd, InverseWorldMatrix);
if (mFlags & LC_PIECE_MODEL)
return mModel->SubModelMinIntersectDist(Start, End, MinDistance);
lcVector3 Min(m_fDimensions[3], m_fDimensions[4], m_fDimensions[5]);
lcVector3 Max(m_fDimensions[0], m_fDimensions[1], m_fDimensions[2]);
@ -139,9 +151,18 @@ bool PieceInfo::MinIntersectDist(const lcMatrix44& WorldMatrix, const lcVector3&
if (mFlags & LC_PIECE_PLACEHOLDER)
return true;
lcVector3 Intersection;
bool Intersect = false;
return mMesh->MinIntersectDist(Start, End, MinDistance, Intersection);
if (mMesh)
{
lcVector3 Intersection;
Intersect = mMesh->MinIntersectDist(Start, End, MinDistance, Intersection);
}
if (mFlags & LC_PIECE_MODEL)
Intersect |= mModel->SubModelMinIntersectDist(Start, End, MinDistance);
return Intersect;
}
bool PieceInfo::BoxTest(const lcMatrix44& WorldMatrix, const lcVector4 WorldPlanes[6]) const
@ -158,9 +179,6 @@ bool PieceInfo::BoxTest(const lcMatrix44& WorldMatrix, const lcVector4 WorldPlan
LocalPlanes[PlaneIdx] = lcVector4(PlaneNormal, WorldPlanes[PlaneIdx][3] - lcDot3(InverseWorldMatrix[3], PlaneNormal));
}
if (mFlags & LC_PIECE_MODEL)
return mModel->SubModelBoxTest(LocalPlanes);
lcVector3 Box[NumCorners] =
{
lcVector3(m_fDimensions[0], m_fDimensions[1], m_fDimensions[5]),
@ -197,10 +215,19 @@ bool PieceInfo::BoxTest(const lcMatrix44& WorldMatrix, const lcVector4 WorldPlan
if (OutcodesAND != 0)
return false;
if (mFlags & LC_PIECE_PLACEHOLDER)
return OutcodesOR == 0;
if (OutcodesOR == 0)
return true;
return OutcodesOR == 0 || mMesh->IntersectsPlanes(LocalPlanes);
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;
}
// Zoom extents for the preview window and print catalog
@ -239,37 +266,61 @@ void PieceInfo::ZoomExtents(const lcMatrix44& ProjectionMatrix, lcMatrix44& View
}
}
void PieceInfo::AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int ColorIndex, bool Focused, bool Selected)
void PieceInfo::AddRenderMesh(lcScene& Scene)
{
if (mFlags & LC_PIECE_MODEL)
{
mModel->SubModelAddRenderMeshes(Scene, WorldMatrix, ColorIndex, Focused, Selected);
if (!mMesh)
return;
}
lcRenderMesh RenderMesh;
RenderMesh.WorldMatrix = WorldMatrix;
RenderMesh.Mesh = (mFlags & LC_PIECE_PLACEHOLDER) ? gPlaceholderMesh : mMesh;
RenderMesh.ColorIndex = ColorIndex;
RenderMesh.Focused = Focused;
RenderMesh.Selected = Selected;
RenderMesh.WorldMatrix = lcMatrix44Identity();
RenderMesh.Mesh = mMesh;
RenderMesh.ColorIndex = gDefaultColor;
RenderMesh.Focused = false;
RenderMesh.Selected = false;
bool Translucent = lcIsColorTranslucent(ColorIndex);
if ((mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((mFlags & LC_PIECE_HAS_DEFAULT) && !Translucent))
if (mFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_DEFAULT | LC_PIECE_HAS_LINES))
Scene.mOpaqueMeshes.Add(RenderMesh);
if ((mFlags & LC_PIECE_HAS_TRANSLUCENT) || ((mFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
if (mFlags & LC_PIECE_HAS_TRANSLUCENT)
{
lcVector3 Pos = lcMul31(WorldMatrix[3], Scene.mViewMatrix);
RenderMesh.Distance = Pos[2];
RenderMesh.Distance = Scene.mViewMatrix.r[3].z;
Scene.mTranslucentMeshes.Add(RenderMesh);
}
}
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);
}
void PieceInfo::GetPartsList(int DefaultColorIndex, lcArray<lcPartsListEntry>& PartsList) const
{
if (mFlags & LC_PIECE_MODEL)

View file

@ -107,12 +107,13 @@ public:
}
void ZoomExtents(const lcMatrix44& ProjectionMatrix, lcMatrix44& ViewMatrix, float* EyePos = NULL) const;
void AddRenderMesh(lcScene& Scene);
void AddRenderMeshes(lcScene& Scene, const lcMatrix44& WorldMatrix, int ColorIndex, bool Focused, bool Selected);
void CreatePlaceholder(const char* Name);
void SetPlaceholder();
void SetModel(lcModel* Model);
void SetModel(lcModel* Model, bool UpdateMesh);
bool IncludesModel(const lcModel* Model) const;
bool MinIntersectDist(const lcMatrix44& WorldMatrix, const lcVector3& WorldStart, const lcVector3& WorldEnd, float& MinDistance) const;
bool BoxTest(const lcMatrix44& WorldMatrix, const lcVector4 Planes[6]) const;