mirror of
https://github.com/leozide/leocad
synced 2025-01-29 20:34:50 +01:00
Sort translucent pieces by distance when rendering.
This commit is contained in:
parent
b0f3abe302
commit
cedfb6af8f
4 changed files with 208 additions and 197 deletions
|
@ -76,7 +76,7 @@ public:
|
|||
{ strcpy(m_strName, name); }
|
||||
const char* GetName()
|
||||
{ return m_strName; }
|
||||
PieceInfo* GetPieceInfo()
|
||||
PieceInfo* GetPieceInfo() const
|
||||
{ return m_pPieceInfo; }
|
||||
void SetStepShow(unsigned char step)
|
||||
{ m_nStepShow = step; }
|
||||
|
@ -98,6 +98,8 @@ public:
|
|||
{ return m_fPosition; }
|
||||
inline Vector3 GetPosition() const
|
||||
{ return Vector3(m_fPosition[0], m_fPosition[1], m_fPosition[2]); }
|
||||
inline Vector4 GetRotation() const
|
||||
{ return Vector4(m_fRotation[0], m_fRotation[1], m_fRotation[2], m_fRotation[3]); }
|
||||
void GetPosition (float* position)
|
||||
{ memcpy(position, m_fPosition, sizeof(m_fPosition)); }
|
||||
void GetRotation (float* rotation)
|
||||
|
|
|
@ -156,7 +156,9 @@ void PieceInfo::LoadIndex(lcFile& file)
|
|||
file.ReadBuffer(m_strDescription, 64);
|
||||
m_strDescription[64] = '\0';
|
||||
file.ReadS16(sh, 6);
|
||||
file.ReadU8(&m_nFlags, 1);
|
||||
lcuint8 Flags;
|
||||
file.ReadU8(&Flags, 1);
|
||||
m_nFlags = Flags;
|
||||
lcuint32 Groups; file.ReadU32(&Groups, 1);
|
||||
file.ReadU32(&m_nOffset, 1);
|
||||
file.ReadU32(&m_nSize, 1);
|
||||
|
@ -543,6 +545,16 @@ void PieceInfo::BuildMesh(void* Data, int* SectionIndices)
|
|||
|
||||
IndexOffset += SectionIndices[ColorIdx * 2 + 0] * sizeof(DstType);
|
||||
NumSections++;
|
||||
|
||||
if (ColorIdx == gDefaultColor)
|
||||
m_nFlags |= LC_PIECE_HAS_DEFAULT;
|
||||
else
|
||||
{
|
||||
if (lcIsColorTranslucent(ColorIdx))
|
||||
m_nFlags |= LC_PIECE_HAS_TRANSLUCENT;
|
||||
else
|
||||
m_nFlags |= LC_PIECE_HAS_SOLID;
|
||||
}
|
||||
}
|
||||
|
||||
if (SectionIndices[ColorIdx * 2 + 1])
|
||||
|
@ -557,6 +569,8 @@ void PieceInfo::BuildMesh(void* Data, int* SectionIndices)
|
|||
|
||||
IndexOffset += SectionIndices[ColorIdx * 2 + 1] * sizeof(DstType);
|
||||
NumSections++;
|
||||
|
||||
m_nFlags |= LC_PIECE_HAS_LINES;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,12 +7,16 @@
|
|||
#endif
|
||||
#include "algebra.h"
|
||||
|
||||
#define LC_PIECE_COUNT 0x01 // Count this piece in the totals ?
|
||||
#define LC_PIECE_LONGDATA_FILE 0x02 // unsigned long/short index
|
||||
#define LC_PIECE_CCW 0x04 // Use back-face culling
|
||||
#define LC_PIECE_SMALL 0x10 // scale = 10000
|
||||
#define LC_PIECE_MEDIUM 0x20 // scale = 1000 (otherwise = 100)
|
||||
#define LC_PIECE_PLACEHOLDER 0x40 // Placeholder for a piece not in the library.
|
||||
#define LC_PIECE_COUNT 0x001 // Count this piece in the totals ?
|
||||
#define LC_PIECE_LONGDATA_FILE 0x002 // unsigned long/short index
|
||||
#define LC_PIECE_CCW 0x004 // Use back-face culling
|
||||
#define LC_PIECE_SMALL 0x010 // scale = 10000
|
||||
#define LC_PIECE_MEDIUM 0x020 // scale = 1000 (otherwise = 100)
|
||||
#define LC_PIECE_PLACEHOLDER 0x040 // Placeholder for a piece not in the library.
|
||||
#define LC_PIECE_HAS_DEFAULT 0x100 // Piece has triangles using the default color
|
||||
#define LC_PIECE_HAS_SOLID 0x200 // Piece has triangles using a solid color
|
||||
#define LC_PIECE_HAS_TRANSLUCENT 0x400 // Piece has triangles using a translucent color
|
||||
#define LC_PIECE_HAS_LINES 0x800 // Piece has lines
|
||||
|
||||
#define LC_PIECE_NAME_LEN 256
|
||||
|
||||
|
@ -81,7 +85,7 @@ public:
|
|||
float m_fDimensions[6];
|
||||
lcuint32 m_nOffset;
|
||||
lcuint32 m_nSize;
|
||||
unsigned char m_nFlags;
|
||||
lcuint32 m_nFlags;
|
||||
|
||||
protected:
|
||||
int m_nRef;
|
||||
|
|
|
@ -1711,166 +1711,26 @@ void Project::RenderBackground(View* view)
|
|||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
typedef struct LC_BSPNODE
|
||||
struct lcTranslucentRenderSection
|
||||
{
|
||||
float plane[4];
|
||||
float Distance;
|
||||
Piece* piece;
|
||||
LC_BSPNODE* front;
|
||||
LC_BSPNODE* back;
|
||||
};
|
||||
|
||||
~LC_BSPNODE()
|
||||
{
|
||||
if (piece == NULL)
|
||||
{
|
||||
if (front)
|
||||
delete front;
|
||||
if (back)
|
||||
delete back;
|
||||
}
|
||||
}
|
||||
} LC_BSPNODE;
|
||||
|
||||
static void RenderBSP(LC_BSPNODE* node, float* eye, bool* bSel, bool bLighting, bool bEdges)
|
||||
int lcTranslucentRenderCompare(const lcTranslucentRenderSection& a, const lcTranslucentRenderSection& b, void*)
|
||||
{
|
||||
if (node->piece)
|
||||
{
|
||||
if (node->piece->IsSelected())
|
||||
{
|
||||
if (!*bSel)
|
||||
{
|
||||
*bSel = true;
|
||||
glLineWidth (2);//*m_fLineWidth);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*bSel)
|
||||
{
|
||||
*bSel = false;
|
||||
glLineWidth(1);//m_fLineWidth);
|
||||
}
|
||||
}
|
||||
|
||||
node->piece->Render(bLighting, bEdges);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eye[0]*node->plane[0] + eye[1]*node->plane[1] +
|
||||
eye[2]*node->plane[2] + node->plane[3] > 0.0f)
|
||||
{
|
||||
RenderBSP(node->back, eye, bSel, bLighting, bEdges);
|
||||
RenderBSP(node->front, eye, bSel, bLighting, bEdges);
|
||||
}
|
||||
if (a.Distance > b.Distance)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
RenderBSP(node->front, eye, bSel, bLighting, bEdges);
|
||||
RenderBSP(node->back, eye, bSel, bLighting, bEdges);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void BuildBSP(LC_BSPNODE* node, Piece* pList)
|
||||
int lcOpaqueRenderCompare(const Piece* a, const Piece* b, void*)
|
||||
{
|
||||
Piece *front_list = NULL, *back_list = NULL;
|
||||
Piece *pPiece, *pNext;
|
||||
|
||||
node->piece = NULL;
|
||||
|
||||
if (pList->m_pLink == NULL)
|
||||
{
|
||||
// This is a leaf
|
||||
node->piece = pList;
|
||||
return;
|
||||
}
|
||||
|
||||
float dx, dy, dz, bs[6] = { 10000, 10000, 10000, -10000, -10000, -10000 };
|
||||
const float *pos;
|
||||
|
||||
for (pPiece = pList; pPiece; pPiece = pPiece->m_pLink)
|
||||
{
|
||||
pos = pPiece->GetConstPosition();
|
||||
if (pos[0] < bs[0]) bs[0] = pos[0];
|
||||
if (pos[1] < bs[1]) bs[1] = pos[1];
|
||||
if (pos[2] < bs[2]) bs[2] = pos[2];
|
||||
if (pos[0] > bs[3]) bs[3] = pos[0];
|
||||
if (pos[1] > bs[4]) bs[4] = pos[1];
|
||||
if (pos[2] > bs[5]) bs[5] = pos[2];
|
||||
}
|
||||
|
||||
dx = ABS(bs[0]-bs[3]);
|
||||
dy = ABS(bs[1]-bs[4]);
|
||||
dz = ABS(bs[2]-bs[5]);
|
||||
|
||||
node->plane[0] = node->plane[1] = node->plane[2] = 0.0f;
|
||||
|
||||
if (dx > dy)
|
||||
{
|
||||
if (dx > dz)
|
||||
node->plane[0] = 1.0f;
|
||||
else
|
||||
node->plane[2] = 1.0f;
|
||||
}
|
||||
if (a->GetPieceInfo() > b->GetPieceInfo())
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
if (dy > dz)
|
||||
node->plane[1] = 1.0f;
|
||||
else
|
||||
node->plane[2] = 1.0f;
|
||||
}
|
||||
|
||||
// D = -Ax -By -Cz
|
||||
node->plane[3] = -(node->plane[0]*(bs[0]+bs[3])/2)-(node->plane[1]*(bs[1]+bs[4])/2)-(node->plane[2]*(bs[2]+bs[5])/2);
|
||||
|
||||
for (pPiece = pList; pPiece;)
|
||||
{
|
||||
pos = pPiece->GetConstPosition();
|
||||
pNext = pPiece->m_pLink;
|
||||
|
||||
if (pos[0]*node->plane[0] + pos[1]*node->plane[1] +
|
||||
pos[2]*node->plane[2] + node->plane[3] > 0.0f)
|
||||
{
|
||||
pPiece->m_pLink = front_list;
|
||||
front_list = pPiece;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPiece->m_pLink = back_list;
|
||||
back_list = pPiece;
|
||||
}
|
||||
|
||||
pPiece = pNext;
|
||||
}
|
||||
|
||||
if (bs[0] == bs[3] && bs[1] == bs[4] && bs[2] == bs[5])
|
||||
{
|
||||
if (back_list)
|
||||
{
|
||||
front_list = back_list;
|
||||
back_list = back_list->m_pLink;
|
||||
front_list->m_pLink = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
back_list = front_list;
|
||||
front_list = front_list->m_pLink;
|
||||
back_list->m_pLink = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (front_list)
|
||||
{
|
||||
node->front = new LC_BSPNODE;
|
||||
BuildBSP(node->front, front_list);
|
||||
}
|
||||
else
|
||||
node->front = NULL;
|
||||
|
||||
if (back_list)
|
||||
{
|
||||
node->back = new LC_BSPNODE;
|
||||
BuildBSP(node->back, back_list);
|
||||
}
|
||||
else
|
||||
node->back = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Project::RenderScenePieces(View* view)
|
||||
|
@ -1901,64 +1761,195 @@ void Project::RenderScenePieces(View* view)
|
|||
if (m_nScene & LC_SCENE_FLOOR)
|
||||
m_pTerrain->Render(view->m_Camera, AspectRatio);
|
||||
|
||||
bool bSel = false;
|
||||
bool bCull = false;
|
||||
Piece* pPiece;
|
||||
PtrArray<Piece> OpaquePieces(512);
|
||||
ObjArray<lcTranslucentRenderSection> TranslucentSections(512);
|
||||
|
||||
LC_BSPNODE tree;
|
||||
tree.front = tree.back = NULL;
|
||||
Piece* pList = NULL;
|
||||
Matrix44 ModelView;
|
||||
Camera* Cam = view->m_Camera;
|
||||
ModelView.CreateLookAt(Cam->GetEyePosition(), Cam->GetTargetPosition(), Cam->GetUpVector());
|
||||
|
||||
// Draw opaque pieces first
|
||||
for (pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
||||
for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
|
||||
{
|
||||
if (!pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
|
||||
continue;
|
||||
|
||||
if (!pPiece->IsTranslucent())
|
||||
bool Translucent = lcIsColorTranslucent(pPiece->mColorIndex);
|
||||
PieceInfo* Info = pPiece->GetPieceInfo();
|
||||
|
||||
if ((Info->m_nFlags & (LC_PIECE_HAS_SOLID | LC_PIECE_HAS_LINES)) || ((Info->m_nFlags & LC_PIECE_HAS_DEFAULT) && !Translucent))
|
||||
OpaquePieces.AddSorted(pPiece, lcOpaqueRenderCompare, NULL);
|
||||
|
||||
if ((Info->m_nFlags & LC_PIECE_HAS_TRANSLUCENT) || ((Info->m_nFlags & LC_PIECE_HAS_DEFAULT) && Translucent))
|
||||
{
|
||||
if (pPiece->IsSelected())
|
||||
Vector3 Pos = Mul31(pPiece->GetPosition(), ModelView);
|
||||
|
||||
lcTranslucentRenderSection RenderSection;
|
||||
|
||||
RenderSection.Distance = Pos[2];
|
||||
RenderSection.piece = pPiece;
|
||||
|
||||
TranslucentSections.AddSorted(RenderSection, lcTranslucentRenderCompare, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
lcMesh* PreviousMesh = NULL;
|
||||
bool PreviousSelected = false;
|
||||
char* ElementsOffset;
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
for (int PieceIdx = 0; PieceIdx < OpaquePieces.GetSize(); PieceIdx++)
|
||||
{
|
||||
Piece* piece = OpaquePieces[PieceIdx];
|
||||
lcMesh* Mesh = piece->GetPieceInfo()->mMesh;
|
||||
|
||||
const Vector3& Position = piece->GetPosition();
|
||||
const Vector4& Rotation = piece->GetRotation();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(Position[0], Position[1], Position[2]);
|
||||
glRotatef(Rotation[3], Rotation[0], Rotation[1], Rotation[2]);
|
||||
|
||||
if (PreviousMesh != Mesh)
|
||||
{
|
||||
if (GL_HasVertexBufferObject())
|
||||
{
|
||||
if (!bSel)
|
||||
{
|
||||
bSel = true;
|
||||
glLineWidth (2*m_fLineWidth);
|
||||
}
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, Mesh->mVertexBuffer.mBuffer);
|
||||
glVertexPointer(3, GL_FLOAT, 0, NULL);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, Mesh->mIndexBuffer.mBuffer);
|
||||
ElementsOffset = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bSel)
|
||||
{
|
||||
bSel = false;
|
||||
glLineWidth(m_fLineWidth);
|
||||
}
|
||||
glVertexPointer(3, GL_FLOAT, 0, Mesh->mVertexBuffer.mData);
|
||||
ElementsOffset = (char*)Mesh->mIndexBuffer.mData;
|
||||
}
|
||||
|
||||
pPiece->Render((m_nDetail & LC_DET_LIGHTING) != 0, (m_nDetail & LC_DET_BRICKEDGES) != 0);
|
||||
PreviousMesh = Mesh;
|
||||
}
|
||||
|
||||
if (piece->IsSelected())
|
||||
{
|
||||
if (!PreviousSelected)
|
||||
glLineWidth(2.0f * m_fLineWidth);
|
||||
|
||||
PreviousSelected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPiece->m_pLink = pList;
|
||||
pList = pPiece;
|
||||
if (PreviousSelected)
|
||||
glLineWidth(m_fLineWidth);
|
||||
|
||||
PreviousSelected = false;
|
||||
}
|
||||
|
||||
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
|
||||
{
|
||||
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
|
||||
int ColorIdx = Section->ColorIndex;
|
||||
|
||||
if (Section->PrimitiveType == GL_TRIANGLES)
|
||||
{
|
||||
if (ColorIdx == gDefaultColor)
|
||||
ColorIdx = piece->mColorIndex;
|
||||
|
||||
if (lcIsColorTranslucent(ColorIdx))
|
||||
continue;
|
||||
|
||||
lcSetColor(ColorIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (piece->IsFocused())
|
||||
lcSetColorFocused();
|
||||
else if (piece->IsSelected())
|
||||
lcSetColorSelected();
|
||||
else if (ColorIdx == gEdgeColor)
|
||||
lcSetEdgeColor(piece->mColorIndex);
|
||||
else
|
||||
lcSetColor(ColorIdx);
|
||||
}
|
||||
|
||||
glDrawElements(Section->PrimitiveType, Section->NumIndices, Mesh->mIndexType, ElementsOffset + Section->IndexOffset);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
if (pList)
|
||||
{
|
||||
float eye[3];
|
||||
view->m_Camera->GetEyePos (eye);
|
||||
BuildBSP(&tree, pList);
|
||||
RenderBSP(&tree, eye, &bSel, (m_nDetail & LC_DET_LIGHTING) != 0, (m_nDetail & LC_DET_BRICKEDGES) != 0);
|
||||
}
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (bSel)
|
||||
if (PreviousSelected)
|
||||
glLineWidth(m_fLineWidth);
|
||||
|
||||
if (bCull)
|
||||
glDisable(GL_CULL_FACE);
|
||||
if (TranslucentSections.GetSize())
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
for (int PieceIdx = 0; PieceIdx < TranslucentSections.GetSize(); PieceIdx++)
|
||||
{
|
||||
Piece* piece = TranslucentSections[PieceIdx].piece;
|
||||
lcMesh* Mesh = piece->GetPieceInfo()->mMesh;
|
||||
|
||||
const Vector3& Position = piece->GetPosition();
|
||||
const Vector4& Rotation = piece->GetRotation();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(Position[0], Position[1], Position[2]);
|
||||
glRotatef(Rotation[3], Rotation[0], Rotation[1], Rotation[2]);
|
||||
|
||||
if (PreviousMesh != Mesh)
|
||||
{
|
||||
if (GL_HasVertexBufferObject())
|
||||
{
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, Mesh->mVertexBuffer.mBuffer);
|
||||
glVertexPointer(3, GL_FLOAT, 0, NULL);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, Mesh->mIndexBuffer.mBuffer);
|
||||
ElementsOffset = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertexPointer(3, GL_FLOAT, 0, Mesh->mVertexBuffer.mData);
|
||||
ElementsOffset = (char*)Mesh->mIndexBuffer.mData;
|
||||
}
|
||||
|
||||
PreviousMesh = Mesh;
|
||||
}
|
||||
|
||||
for (int SectionIdx = 0; SectionIdx < Mesh->mNumSections; SectionIdx++)
|
||||
{
|
||||
lcMeshSection* Section = &Mesh->mSections[SectionIdx];
|
||||
int ColorIdx = Section->ColorIndex;
|
||||
|
||||
if (Section->PrimitiveType != GL_TRIANGLES)
|
||||
continue;
|
||||
|
||||
if (ColorIdx == gDefaultColor)
|
||||
ColorIdx = piece->mColorIndex;
|
||||
|
||||
if (!lcIsColorTranslucent(ColorIdx))
|
||||
continue;
|
||||
|
||||
lcSetColor(ColorIdx);
|
||||
|
||||
glDrawElements(Section->PrimitiveType, Section->NumIndices, Mesh->mIndexType, ElementsOffset + Section->IndexOffset);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (GL_HasVertexBufferObject())
|
||||
{
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
else
|
||||
glVertexPointer(3, GL_FLOAT, 0, NULL);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void Project::RenderSceneBoxes(View* view)
|
||||
|
|
Loading…
Add table
Reference in a new issue