2017-04-02 01:53:54 +02:00
|
|
|
#include "lc_global.h"
|
|
|
|
#include "lc_scene.h"
|
|
|
|
#include "lc_context.h"
|
|
|
|
#include "pieceinf.h"
|
|
|
|
#include "lc_texture.h"
|
|
|
|
#include "lc_library.h"
|
|
|
|
#include "lc_application.h"
|
|
|
|
#include "object.h"
|
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
bool gTranslucentFade = true; // todo: move to preferences
|
|
|
|
|
2017-04-02 01:53:54 +02:00
|
|
|
lcScene::lcScene()
|
|
|
|
: mRenderMeshes(0, 1024), mOpaqueMeshes(0, 1024), mTranslucentMeshes(0, 1024), mInterfaceObjects(0, 1024)
|
|
|
|
{
|
2018-04-07 20:45:00 +02:00
|
|
|
mActiveSubmodelInstance = nullptr;
|
2019-12-07 17:31:56 +01:00
|
|
|
mDrawInterface = false;
|
2018-04-08 00:28:44 +02:00
|
|
|
mAllowWireframe = true;
|
2019-11-28 21:47:19 +01:00
|
|
|
mAllowLOD = true;
|
2019-11-30 20:38:11 +01:00
|
|
|
mPreTranslucentCallback = nullptr;
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcScene::Begin(const lcMatrix44& ViewMatrix)
|
|
|
|
{
|
|
|
|
mViewMatrix = ViewMatrix;
|
2018-04-07 20:45:00 +02:00
|
|
|
mActiveSubmodelInstance = nullptr;
|
2019-11-30 20:38:11 +01:00
|
|
|
mPreTranslucentCallback = nullptr;
|
2017-04-02 01:53:54 +02:00
|
|
|
mRenderMeshes.RemoveAll();
|
|
|
|
mOpaqueMeshes.RemoveAll();
|
|
|
|
mTranslucentMeshes.RemoveAll();
|
|
|
|
mInterfaceObjects.RemoveAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcScene::End()
|
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const auto OpaqueMeshCompare = [this](int Index1, int Index2)
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
2019-11-13 00:11:03 +01:00
|
|
|
const lcMesh* Mesh1 = mRenderMeshes[Index1].Mesh;
|
|
|
|
const lcMesh* Mesh2 = mRenderMeshes[Index2].Mesh;
|
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
const int Texture1 = Mesh1->mFlags & lcMeshFlag::HasTexture;
|
|
|
|
const int Texture2 = Mesh2->mFlags & lcMeshFlag::HasTexture;
|
2019-11-13 00:11:03 +01:00
|
|
|
|
|
|
|
if (Texture1 == Texture2)
|
|
|
|
return Mesh1 < Mesh2;
|
|
|
|
|
|
|
|
return Texture1 ? false : true;
|
2017-04-02 01:53:54 +02:00
|
|
|
};
|
|
|
|
|
2019-03-29 01:59:58 +01:00
|
|
|
std::sort(mOpaqueMeshes.begin(), mOpaqueMeshes.end(), OpaqueMeshCompare);
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-02-24 23:31:08 +01:00
|
|
|
auto TranslucentMeshCompare = [](const lcTranslucentMeshInstance& Mesh1, const lcTranslucentMeshInstance& Mesh2)
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
2019-11-23 01:47:58 +01:00
|
|
|
return Mesh1.Distance > Mesh2.Distance;
|
2017-04-02 01:53:54 +02:00
|
|
|
};
|
|
|
|
|
2019-03-29 01:59:58 +01:00
|
|
|
std::sort(mTranslucentMeshes.begin(), mTranslucentMeshes.end(), TranslucentMeshCompare);
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
|
2019-07-21 17:56:37 +02:00
|
|
|
void lcScene::AddMesh(lcMesh* Mesh, const lcMatrix44& WorldMatrix, int ColorIndex, lcRenderMeshState State)
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
|
|
|
lcRenderMesh& RenderMesh = mRenderMeshes.Add();
|
|
|
|
|
|
|
|
RenderMesh.WorldMatrix = WorldMatrix;
|
|
|
|
RenderMesh.Mesh = Mesh;
|
|
|
|
RenderMesh.ColorIndex = ColorIndex;
|
|
|
|
RenderMesh.State = State;
|
2020-03-23 04:18:52 +01:00
|
|
|
const float Distance = fabsf(lcMul31(WorldMatrix[3], mViewMatrix).z);
|
2019-11-28 21:47:19 +01:00
|
|
|
RenderMesh.LodIndex = mAllowLOD ? RenderMesh.Mesh->GetLodIndex(Distance) : LC_MESH_LOD_HIGH;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
const bool ForceTranslucent = (gTranslucentFade && State == lcRenderMeshState::Faded);
|
|
|
|
const bool Translucent = lcIsColorTranslucent(ColorIndex) || ForceTranslucent;
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcMeshFlags Flags = Mesh->mFlags;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2019-07-21 17:56:37 +02:00
|
|
|
if ((Flags & (lcMeshFlag::HasSolid | lcMeshFlag::HasLines)) || ((Flags & lcMeshFlag::HasDefault) && !Translucent))
|
2017-04-02 01:53:54 +02:00
|
|
|
mOpaqueMeshes.Add(mRenderMeshes.GetSize() - 1);
|
|
|
|
|
2019-07-21 17:56:37 +02:00
|
|
|
if ((Flags & lcMeshFlag::HasTranslucent) || ((Flags & lcMeshFlag::HasDefault) && Translucent))
|
2019-11-23 01:47:58 +01:00
|
|
|
{
|
|
|
|
const lcMeshLod& Lod = Mesh->mLods[RenderMesh.LodIndex];
|
|
|
|
|
|
|
|
for (int SectionIdx = 0; SectionIdx < Lod.NumSections; SectionIdx++)
|
|
|
|
{
|
|
|
|
const lcMeshSection* Section = &Lod.Sections[SectionIdx];
|
|
|
|
|
|
|
|
if ((Section->PrimitiveType & (LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES)) == 0)
|
|
|
|
continue;
|
|
|
|
|
2020-01-19 01:53:33 +01:00
|
|
|
int SectionColorIndex = Section->ColorIndex;
|
2019-11-23 01:47:58 +01:00
|
|
|
|
2020-01-19 01:53:33 +01:00
|
|
|
if (SectionColorIndex == gDefaultColor)
|
|
|
|
SectionColorIndex = RenderMesh.ColorIndex;
|
2019-11-23 01:47:58 +01:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (!lcIsColorTranslucent(SectionColorIndex) && !ForceTranslucent)
|
2019-11-23 01:47:58 +01:00
|
|
|
continue;
|
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcVector3 Center = (Section->BoundingBox.Min + Section->BoundingBox.Max) / 2;
|
|
|
|
const float InstanceDistance = fabsf(lcMul31(lcMul31(Center, WorldMatrix), mViewMatrix).z);
|
2019-11-23 01:47:58 +01:00
|
|
|
|
|
|
|
lcTranslucentMeshInstance& Instance = mTranslucentMeshes.Add();
|
|
|
|
Instance.Section = Section;
|
2020-01-19 01:53:33 +01:00
|
|
|
Instance.Distance = InstanceDistance;
|
2019-11-23 01:47:58 +01:00
|
|
|
Instance.RenderMeshIndex = mRenderMeshes.GetSize() - 1;
|
|
|
|
}
|
|
|
|
}
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
void lcScene::DrawDebugNormals(lcContext* Context, const lcMesh* Mesh) const
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcVertex* const VertexBuffer = (lcVertex*)Mesh->mVertexData;
|
|
|
|
lcVector3* const Vertices = (lcVector3*)malloc(Mesh->mNumVertices * 2 * sizeof(lcVector3));
|
2019-11-23 01:47:58 +01:00
|
|
|
|
|
|
|
for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++)
|
|
|
|
{
|
|
|
|
Vertices[VertexIdx * 2] = VertexBuffer[VertexIdx].Position;
|
|
|
|
Vertices[VertexIdx * 2 + 1] = VertexBuffer[VertexIdx].Position + lcUnpackNormal(VertexBuffer[VertexIdx].Normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
Context->SetVertexBufferPointer(Vertices);
|
|
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->DrawPrimitives(GL_LINES, 0, Mesh->mNumVertices * 2);
|
|
|
|
free(Vertices);
|
|
|
|
}
|
2019-11-13 00:11:03 +01:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
void lcScene::DrawOpaqueMeshes(lcContext* Context, bool DrawLit, int PrimitiveTypes, bool DrawFaded, bool DrawNonFaded) const
|
2019-11-23 01:47:58 +01:00
|
|
|
{
|
|
|
|
if (mOpaqueMeshes.IsEmpty())
|
2019-11-13 00:11:03 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
lcMaterialType FlatMaterial, TexturedMaterial;
|
|
|
|
|
2019-11-23 01:47:58 +01:00
|
|
|
if (DrawLit)
|
2019-11-13 00:11:03 +01:00
|
|
|
{
|
2020-03-22 21:44:20 +01:00
|
|
|
FlatMaterial = lcMaterialType::FakeLitColor;
|
|
|
|
TexturedMaterial = lcMaterialType::FakeLitTextureDecal;
|
2019-11-13 00:11:03 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-22 21:44:20 +01:00
|
|
|
FlatMaterial = lcMaterialType::UnlitColor;
|
|
|
|
TexturedMaterial = lcMaterialType::UnlitTextureDecal;
|
2019-11-13 00:11:03 +01:00
|
|
|
}
|
|
|
|
|
2020-03-22 21:44:20 +01:00
|
|
|
Context->SetPolygonOffset(lcPolygonOffset::Opaque);
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
for (const int MeshIndex : mOpaqueMeshes)
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
|
|
|
const lcRenderMesh& RenderMesh = mRenderMeshes[MeshIndex];
|
|
|
|
const lcMesh* Mesh = RenderMesh.Mesh;
|
2020-03-23 04:18:52 +01:00
|
|
|
const int LodIndex = RenderMesh.LodIndex;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (!DrawFaded && RenderMesh.State == lcRenderMeshState::Faded)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!DrawNonFaded && RenderMesh.State != lcRenderMeshState::Faded)
|
|
|
|
continue;
|
|
|
|
|
2017-04-02 01:53:54 +02:00
|
|
|
Context->BindMesh(Mesh);
|
|
|
|
Context->SetWorldMatrix(RenderMesh.WorldMatrix);
|
|
|
|
|
|
|
|
for (int SectionIdx = 0; SectionIdx < Mesh->mLods[LodIndex].NumSections; SectionIdx++)
|
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcMeshSection* const Section = &Mesh->mLods[LodIndex].Sections[SectionIdx];
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2019-11-13 00:11:03 +01:00
|
|
|
if ((Section->PrimitiveType & PrimitiveTypes) == 0)
|
2017-04-02 01:53:54 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
int ColorIndex = Section->ColorIndex;
|
|
|
|
|
|
|
|
if (Section->PrimitiveType & (LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES))
|
|
|
|
{
|
|
|
|
if (ColorIndex == gDefaultColor)
|
|
|
|
ColorIndex = RenderMesh.ColorIndex;
|
|
|
|
|
2019-11-23 01:47:58 +01:00
|
|
|
if (lcIsColorTranslucent(ColorIndex))
|
2017-04-02 01:53:54 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (RenderMesh.State)
|
|
|
|
{
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Default:
|
|
|
|
case lcRenderMeshState::Highlighted:
|
2017-04-02 01:53:54 +02:00
|
|
|
Context->SetColorIndex(ColorIndex);
|
|
|
|
break;
|
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Selected:
|
2018-03-29 19:20:36 +02:00
|
|
|
Context->SetColorIndexTinted(ColorIndex, LC_COLOR_SELECTED, 0.5f);
|
2017-04-02 01:53:54 +02:00
|
|
|
break;
|
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Focused:
|
2018-03-29 19:20:36 +02:00
|
|
|
Context->SetColorIndexTinted(ColorIndex, LC_COLOR_FOCUSED, 0.5f);
|
|
|
|
break;
|
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Faded:
|
2020-04-20 05:21:18 +02:00
|
|
|
if (gTranslucentFade)
|
|
|
|
continue;
|
2018-03-29 19:20:36 +02:00
|
|
|
Context->SetColorIndexTinted(ColorIndex, LC_COLOR_DISABLED, 0.25f);
|
2017-04-02 01:53:54 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-11-02 19:38:24 +01:00
|
|
|
else if (Section->PrimitiveType & LC_MESH_LINES)
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
|
|
|
switch (RenderMesh.State)
|
|
|
|
{
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Default:
|
2017-04-02 01:53:54 +02:00
|
|
|
if (ColorIndex == gEdgeColor)
|
|
|
|
Context->SetEdgeColorIndex(RenderMesh.ColorIndex);
|
|
|
|
else
|
|
|
|
Context->SetColorIndex(ColorIndex);
|
|
|
|
break;
|
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Selected:
|
2017-04-02 01:53:54 +02:00
|
|
|
Context->SetInterfaceColor(LC_COLOR_SELECTED);
|
|
|
|
break;
|
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Focused:
|
2017-04-02 01:53:54 +02:00
|
|
|
Context->SetInterfaceColor(LC_COLOR_FOCUSED);
|
|
|
|
break;
|
2017-06-20 03:30:54 +02:00
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Highlighted:
|
2017-06-20 03:30:54 +02:00
|
|
|
Context->SetInterfaceColor(LC_COLOR_HIGHLIGHT);
|
|
|
|
break;
|
2018-03-29 19:20:36 +02:00
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Faded:
|
2020-04-20 05:21:18 +02:00
|
|
|
if (gTranslucentFade)
|
|
|
|
Context->SetEdgeColorIndexTintedAlpha(ColorIndex, LC_COLOR_DISABLED_TRANSLUCENT, 0.25f);
|
|
|
|
else
|
|
|
|
Context->SetEdgeColorIndexTinted(ColorIndex, LC_COLOR_DISABLED, 0.25f);
|
2018-03-29 19:20:36 +02:00
|
|
|
break;
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (Section->PrimitiveType == LC_MESH_CONDITIONAL_LINES)
|
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcMatrix44 WorldViewProjectionMatrix = lcMul(RenderMesh.WorldMatrix, lcMul(mViewMatrix, Context->GetProjectionMatrix()));
|
|
|
|
const lcVertex* const VertexBuffer = (lcVertex*)Mesh->mVertexData;
|
|
|
|
const int IndexBufferOffset = Mesh->mIndexCacheOffset != -1 ? Mesh->mIndexCacheOffset : 0;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
const int VertexBufferOffset = Mesh->mVertexCacheOffset != -1 ? Mesh->mVertexCacheOffset : 0;
|
2019-11-23 01:47:58 +01:00
|
|
|
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 0, 0, DrawLit);
|
2017-06-23 03:45:45 +02:00
|
|
|
|
2017-04-02 01:53:54 +02:00
|
|
|
if (Mesh->mIndexType == GL_UNSIGNED_SHORT)
|
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const quint16* const Indices = (quint16*)((char*)Mesh->mIndexData + Section->IndexOffset);
|
2017-04-02 01:53:54 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < Section->NumIndices; i += 4)
|
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcVector3 p1 = lcMul31(VertexBuffer[Indices[i + 0]].Position, WorldViewProjectionMatrix);
|
|
|
|
const lcVector3 p2 = lcMul31(VertexBuffer[Indices[i + 1]].Position, WorldViewProjectionMatrix);
|
|
|
|
const lcVector3 p3 = lcMul31(VertexBuffer[Indices[i + 2]].Position, WorldViewProjectionMatrix);
|
|
|
|
const lcVector3 p4 = lcMul31(VertexBuffer[Indices[i + 3]].Position, WorldViewProjectionMatrix);
|
2017-04-02 01:53:54 +02:00
|
|
|
|
|
|
|
if (((p1.y - p2.y) * (p3.x - p1.x) + (p2.x - p1.x) * (p3.y - p1.y)) * ((p1.y - p2.y) * (p4.x - p1.x) + (p2.x - p1.x) * (p4.y - p1.y)) >= 0)
|
2017-12-02 21:22:04 +01:00
|
|
|
Context->DrawIndexedPrimitives(GL_LINES, 2, Mesh->mIndexType, IndexBufferOffset + Section->IndexOffset + i * sizeof(quint16));
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const quint32* const Indices = (quint32*)((char*)Mesh->mIndexData + Section->IndexOffset);
|
2017-04-02 01:53:54 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < Section->NumIndices; i += 4)
|
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcVector3 p1 = lcMul31(VertexBuffer[Indices[i + 0]].Position, WorldViewProjectionMatrix);
|
|
|
|
const lcVector3 p2 = lcMul31(VertexBuffer[Indices[i + 1]].Position, WorldViewProjectionMatrix);
|
|
|
|
const lcVector3 p3 = lcMul31(VertexBuffer[Indices[i + 2]].Position, WorldViewProjectionMatrix);
|
|
|
|
const lcVector3 p4 = lcMul31(VertexBuffer[Indices[i + 3]].Position, WorldViewProjectionMatrix);
|
2017-04-02 01:53:54 +02:00
|
|
|
|
|
|
|
if (((p1.y - p2.y) * (p3.x - p1.x) + (p2.x - p1.x) * (p3.y - p1.y)) * ((p1.y - p2.y) * (p4.x - p1.x) + (p2.x - p1.x) * (p4.y - p1.y)) >= 0)
|
2017-12-02 21:22:04 +01:00
|
|
|
Context->DrawIndexedPrimitives(GL_LINES, 2, Mesh->mIndexType, IndexBufferOffset + Section->IndexOffset + i * sizeof(quint32));
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
}
|
2017-06-23 03:45:45 +02:00
|
|
|
|
|
|
|
continue;
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcTexture* const Texture = Section->Texture;
|
2017-04-02 01:53:54 +02:00
|
|
|
int VertexBufferOffset = Mesh->mVertexCacheOffset != -1 ? Mesh->mVertexCacheOffset : 0;
|
2020-03-23 04:18:52 +01:00
|
|
|
const int IndexBufferOffset = Mesh->mIndexCacheOffset != -1 ? Mesh->mIndexCacheOffset : 0;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
|
|
|
if (!Texture)
|
|
|
|
{
|
2019-11-13 00:11:03 +01:00
|
|
|
Context->SetMaterial(FlatMaterial);
|
2019-11-23 01:47:58 +01:00
|
|
|
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 0, 0, DrawLit);
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-13 00:11:03 +01:00
|
|
|
Context->SetMaterial(TexturedMaterial);
|
2017-04-02 01:53:54 +02:00
|
|
|
VertexBufferOffset += Mesh->mNumVertices * sizeof(lcVertex);
|
2019-11-23 01:47:58 +01:00
|
|
|
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 2, 0, DrawLit);
|
2017-12-26 19:19:20 +01:00
|
|
|
Context->BindTexture2D(Texture->mTexture);
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
const GLenum DrawPrimitiveType = Section->PrimitiveType & (LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES) ? GL_TRIANGLES : GL_LINES;
|
2017-04-02 01:53:54 +02:00
|
|
|
Context->DrawIndexedPrimitives(DrawPrimitiveType, Section->NumIndices, Mesh->mIndexType, IndexBufferOffset + Section->IndexOffset);
|
|
|
|
}
|
|
|
|
|
2019-11-23 01:47:58 +01:00
|
|
|
#ifdef LC_DEBUG_NORMALS
|
|
|
|
DrawDebugNormals(Context, Mesh);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
Context->BindTexture2D(0);
|
2020-03-22 21:44:20 +01:00
|
|
|
Context->SetPolygonOffset(lcPolygonOffset::None);
|
2019-11-23 01:47:58 +01:00
|
|
|
}
|
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
void lcScene::DrawTranslucentMeshes(lcContext* Context, bool DrawLit, bool DrawFadePrepass, bool DrawFaded, bool DrawNonFaded) const
|
2019-11-23 01:47:58 +01:00
|
|
|
{
|
|
|
|
if (mTranslucentMeshes.IsEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
lcMaterialType FlatMaterial, TexturedMaterial;
|
|
|
|
|
|
|
|
if (DrawLit)
|
|
|
|
{
|
2020-03-22 21:44:20 +01:00
|
|
|
FlatMaterial = lcMaterialType::FakeLitColor;
|
|
|
|
TexturedMaterial = lcMaterialType::FakeLitTextureDecal;
|
2019-11-23 01:47:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-22 21:44:20 +01:00
|
|
|
FlatMaterial = lcMaterialType::UnlitColor;
|
|
|
|
TexturedMaterial = lcMaterialType::UnlitTextureDecal;
|
2019-11-23 01:47:58 +01:00
|
|
|
}
|
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (!DrawFadePrepass)
|
|
|
|
{
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
Context->SetDepthWrite(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
|
|
|
|
2020-03-22 21:44:20 +01:00
|
|
|
Context->SetPolygonOffset(lcPolygonOffset::Translucent);
|
2019-11-23 01:47:58 +01:00
|
|
|
|
|
|
|
for (const lcTranslucentMeshInstance& MeshInstance : mTranslucentMeshes)
|
|
|
|
{
|
|
|
|
const lcRenderMesh& RenderMesh = mRenderMeshes[MeshInstance.RenderMeshIndex];
|
|
|
|
const lcMesh* Mesh = RenderMesh.Mesh;
|
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (!DrawFaded && RenderMesh.State == lcRenderMeshState::Faded)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!DrawNonFaded && RenderMesh.State != lcRenderMeshState::Faded)
|
|
|
|
continue;
|
|
|
|
|
2019-11-23 01:47:58 +01:00
|
|
|
Context->BindMesh(Mesh);
|
|
|
|
Context->SetWorldMatrix(RenderMesh.WorldMatrix);
|
|
|
|
|
|
|
|
const lcMeshSection* Section = MeshInstance.Section;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2019-11-23 01:47:58 +01:00
|
|
|
int ColorIndex = Section->ColorIndex;
|
|
|
|
|
|
|
|
if (ColorIndex == gDefaultColor)
|
|
|
|
ColorIndex = RenderMesh.ColorIndex;
|
|
|
|
|
|
|
|
switch (RenderMesh.State)
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Default:
|
|
|
|
case lcRenderMeshState::Highlighted:
|
2019-11-23 01:47:58 +01:00
|
|
|
Context->SetColorIndex(ColorIndex);
|
|
|
|
break;
|
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Selected:
|
2019-11-23 01:47:58 +01:00
|
|
|
Context->SetColorIndexTinted(ColorIndex, LC_COLOR_SELECTED, 0.5f);
|
|
|
|
break;
|
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Focused:
|
2019-11-23 01:47:58 +01:00
|
|
|
Context->SetColorIndexTinted(ColorIndex, LC_COLOR_FOCUSED, 0.5f);
|
|
|
|
break;
|
|
|
|
|
2020-01-02 02:06:17 +01:00
|
|
|
case lcRenderMeshState::Faded:
|
2020-04-20 05:21:18 +02:00
|
|
|
if (gTranslucentFade)
|
|
|
|
Context->SetColorIndexTintedAlpha(ColorIndex, LC_COLOR_DISABLED_TRANSLUCENT, 0.25f);
|
|
|
|
else
|
|
|
|
Context->SetColorIndexTinted(ColorIndex, LC_COLOR_DISABLED, 0.25f);
|
2019-11-23 01:47:58 +01:00
|
|
|
break;
|
|
|
|
}
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
const lcTexture* Texture = Section->Texture;
|
2019-11-23 01:47:58 +01:00
|
|
|
int VertexBufferOffset = Mesh->mVertexCacheOffset != -1 ? Mesh->mVertexCacheOffset : 0;
|
2020-03-23 04:18:52 +01:00
|
|
|
const int IndexBufferOffset = Mesh->mIndexCacheOffset != -1 ? Mesh->mIndexCacheOffset : 0;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2019-11-23 01:47:58 +01:00
|
|
|
if (!Texture)
|
|
|
|
{
|
|
|
|
Context->SetMaterial(FlatMaterial);
|
|
|
|
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 0, 0, DrawLit);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Context->SetMaterial(TexturedMaterial);
|
|
|
|
VertexBufferOffset += Mesh->mNumVertices * sizeof(lcVertex);
|
|
|
|
Context->SetVertexFormat(VertexBufferOffset, 3, 1, 2, 0, DrawLit);
|
|
|
|
Context->BindTexture2D(Texture->mTexture);
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
2019-11-23 01:47:58 +01:00
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
const GLenum DrawPrimitiveType = Section->PrimitiveType & (LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES) ? GL_TRIANGLES : GL_LINES;
|
2019-11-23 01:47:58 +01:00
|
|
|
Context->DrawIndexedPrimitives(DrawPrimitiveType, Section->NumIndices, Mesh->mIndexType, IndexBufferOffset + Section->IndexOffset);
|
|
|
|
|
|
|
|
#ifdef LC_DEBUG_NORMALS
|
|
|
|
DrawDebugNormals(Context, Mesh);
|
2017-04-02 01:53:54 +02:00
|
|
|
#endif
|
|
|
|
}
|
2019-11-13 00:11:03 +01:00
|
|
|
|
2019-11-18 23:32:53 +01:00
|
|
|
Context->BindTexture2D(0);
|
2020-03-22 21:44:20 +01:00
|
|
|
Context->SetPolygonOffset(lcPolygonOffset::None);
|
2019-11-18 23:32:53 +01:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (!DrawFadePrepass)
|
|
|
|
{
|
|
|
|
Context->SetDepthWrite(true);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void lcScene::Draw(lcContext* Context) const
|
|
|
|
{
|
2017-12-22 14:42:28 +01:00
|
|
|
// TODO: find a better place for these updates
|
|
|
|
lcGetPiecesLibrary()->UpdateBuffers(Context);
|
2018-09-30 04:45:21 +02:00
|
|
|
lcGetPiecesLibrary()->UploadTextures(Context);
|
2017-04-02 01:53:54 +02:00
|
|
|
|
|
|
|
Context->SetViewMatrix(mViewMatrix);
|
|
|
|
|
2020-03-23 04:18:52 +01:00
|
|
|
constexpr bool DrawConditional = false;
|
2018-07-31 20:33:32 +02:00
|
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
2017-06-23 03:45:45 +02:00
|
|
|
|
2018-07-31 20:33:32 +02:00
|
|
|
lcShadingMode ShadingMode = Preferences.mShadingMode;
|
2020-03-22 21:44:20 +01:00
|
|
|
if (ShadingMode == lcShadingMode::Wireframe && !mAllowWireframe)
|
|
|
|
ShadingMode = lcShadingMode::Flat;
|
2017-08-25 21:57:14 +02:00
|
|
|
|
2020-03-22 21:44:20 +01:00
|
|
|
if (ShadingMode == lcShadingMode::Wireframe)
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
2019-11-13 00:11:03 +01:00
|
|
|
int PrimitiveTypes = LC_MESH_LINES;
|
2017-11-26 00:47:37 +01:00
|
|
|
|
|
|
|
if (DrawConditional)
|
2019-11-13 00:11:03 +01:00
|
|
|
PrimitiveTypes |= LC_MESH_CONDITIONAL_LINES;
|
2017-08-25 21:57:14 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
DrawOpaqueMeshes(Context, false, PrimitiveTypes, true, true);
|
2019-11-30 20:38:11 +01:00
|
|
|
|
|
|
|
if (mPreTranslucentCallback)
|
|
|
|
mPreTranslucentCallback();
|
2017-11-26 00:47:37 +01:00
|
|
|
}
|
2020-03-22 21:44:20 +01:00
|
|
|
else if (ShadingMode == lcShadingMode::Flat)
|
2017-11-26 00:47:37 +01:00
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const bool DrawLines = Preferences.mDrawEdgeLines && Preferences.mLineWidth != 0.0f;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
int LinePrimitiveTypes = LC_MESH_LINES;
|
2017-06-23 03:45:45 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (DrawConditional)
|
|
|
|
LinePrimitiveTypes |= LC_MESH_CONDITIONAL_LINES;
|
|
|
|
|
|
|
|
const int SolidPrimitiveTypes = LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES;
|
|
|
|
|
|
|
|
if (gTranslucentFade)
|
2017-06-23 03:45:45 +02:00
|
|
|
{
|
2020-04-20 05:21:18 +02:00
|
|
|
DrawOpaqueMeshes(Context, false, SolidPrimitiveTypes | LinePrimitiveTypes, false, true);
|
2017-06-23 03:45:45 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (mPreTranslucentCallback)
|
|
|
|
mPreTranslucentCallback();
|
2019-11-09 20:54:17 +01:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
DrawTranslucentMeshes(Context, false, true, true, false);
|
2019-11-30 20:38:11 +01:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (DrawLines)
|
|
|
|
DrawOpaqueMeshes(Context, false, LinePrimitiveTypes, true, false);
|
|
|
|
|
|
|
|
DrawTranslucentMeshes(Context, true, false, true, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DrawOpaqueMeshes(Context, false, SolidPrimitiveTypes | LinePrimitiveTypes, true, true);
|
2019-11-30 20:38:11 +01:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (mPreTranslucentCallback)
|
|
|
|
mPreTranslucentCallback();
|
|
|
|
|
|
|
|
DrawTranslucentMeshes(Context, true, false, true, true);
|
|
|
|
}
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-03-23 04:18:52 +01:00
|
|
|
const bool DrawLines = Preferences.mDrawEdgeLines && Preferences.mLineWidth != 0.0f;
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
int LinePrimitiveTypes = LC_MESH_LINES;
|
|
|
|
|
|
|
|
if (DrawConditional)
|
|
|
|
LinePrimitiveTypes |= LC_MESH_CONDITIONAL_LINES;
|
|
|
|
|
|
|
|
if (gTranslucentFade)
|
2017-04-02 01:53:54 +02:00
|
|
|
{
|
2020-04-20 05:21:18 +02:00
|
|
|
DrawOpaqueMeshes(Context, true, LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES, false, true);
|
|
|
|
|
|
|
|
if (DrawLines)
|
|
|
|
DrawOpaqueMeshes(Context, false, LinePrimitiveTypes, false, true);
|
|
|
|
|
|
|
|
if (mPreTranslucentCallback)
|
|
|
|
mPreTranslucentCallback();
|
2017-06-23 03:45:45 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
DrawTranslucentMeshes(Context, false, true, true, false);
|
2017-06-23 03:45:45 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (DrawLines)
|
|
|
|
DrawOpaqueMeshes(Context, false, LinePrimitiveTypes, true, false);
|
|
|
|
|
|
|
|
DrawTranslucentMeshes(Context, true, false, true, true);
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
2020-04-20 05:21:18 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (DrawLines)
|
|
|
|
DrawOpaqueMeshes(Context, false, LinePrimitiveTypes, true, true);
|
2017-04-02 01:53:54 +02:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
DrawOpaqueMeshes(Context, true, LC_MESH_TRIANGLES | LC_MESH_TEXTURED_TRIANGLES, true, true);
|
2019-11-30 20:38:11 +01:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
if (mPreTranslucentCallback)
|
|
|
|
mPreTranslucentCallback();
|
2019-11-30 20:38:11 +01:00
|
|
|
|
2020-04-20 05:21:18 +02:00
|
|
|
DrawTranslucentMeshes(Context, true, false, true, true);
|
|
|
|
}
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void lcScene::DrawInterfaceObjects(lcContext* Context) const
|
|
|
|
{
|
|
|
|
for (const lcObject* Object : mInterfaceObjects)
|
2018-04-08 02:17:32 +02:00
|
|
|
Object->DrawInterface(Context, *this);
|
2017-04-02 01:53:54 +02:00
|
|
|
}
|