forked from Mirrors/openclonk
Draw only partial set of faces for buildings in construction
parent
de67769065
commit
7f5f916e76
|
@ -568,7 +568,7 @@ void C4Def::Draw(C4Facet &cgo, bool fSelected, DWORD iColor, C4Object *pObj, int
|
|||
}
|
||||
else
|
||||
{
|
||||
dummy.reset(new StdMeshInstance(*graphics->Mesh));
|
||||
dummy.reset(new StdMeshInstance(*graphics->Mesh, 1.0f));
|
||||
instance = dummy.get();
|
||||
GetProperty(P_PictureTransformation, &value);
|
||||
}
|
||||
|
|
|
@ -595,7 +595,7 @@ void C4GraphicsOverlay::UpdateFacet()
|
|||
if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap)
|
||||
fctBlit.Set(pSourceGfx->GetBitmap(), 0, 0, pDef->Shape.Wdt, pDef->Shape.Hgt, pDef->Shape.x+pDef->Shape.Wdt/2, pDef->Shape.y+pDef->Shape.Hgt/2);
|
||||
else
|
||||
pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh);
|
||||
pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh, 1.0f);
|
||||
break;
|
||||
|
||||
case MODE_Action: // graphics of specified action
|
||||
|
@ -630,7 +630,7 @@ void C4GraphicsOverlay::UpdateFacet()
|
|||
C4String* AnimationName = action->GetPropertyStr(P_Animation);
|
||||
if (!AnimationName) return;
|
||||
|
||||
pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh);
|
||||
pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh, 1.0f);
|
||||
const StdMeshAnimation* Animation = pSourceGfx->Mesh->GetAnimationByName(AnimationName->GetData());
|
||||
if (!Animation) return;
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ bool C4Object::Init(C4PropList *pDef, C4Object *pCreator,
|
|||
pGraphics = &Def->Graphics;
|
||||
if (pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
||||
{
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh, Def->GrowthType ? 1.0f : static_cast<float>(Con)/static_cast<float>(FullCon));
|
||||
pMeshInstance->SetFaceOrderingForClrModulation(ColorMod);
|
||||
}
|
||||
else
|
||||
|
@ -487,7 +487,7 @@ void C4Object::UpdateGraphics(bool fGraphicsChanged, bool fTemp)
|
|||
delete pMeshInstance;
|
||||
if (pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
||||
{
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh, Def->GrowthType ? 1.0f : static_cast<float>(Con)/static_cast<float>(FullCon));
|
||||
pMeshInstance->SetFaceOrderingForClrModulation(ColorMod);
|
||||
}
|
||||
else
|
||||
|
@ -1333,7 +1333,9 @@ void C4Object::DoCon(int32_t iChange)
|
|||
// Con Zero Removal
|
||||
if (Con<=0)
|
||||
AssignRemoval();
|
||||
|
||||
// Mesh Graphics Update
|
||||
else if(pMeshInstance)
|
||||
pMeshInstance->SetCompletion(Def->GrowthType ? 1.0f : static_cast<float>(Con)/static_cast<float>(FullCon));
|
||||
}
|
||||
|
||||
void C4Object::DoExperience(int32_t change)
|
||||
|
@ -2384,7 +2386,7 @@ void C4Object::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers)
|
|||
if(pComp->isCompiler())
|
||||
{
|
||||
assert(!pMeshInstance);
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh, Def->GrowthType ? 1.0f : static_cast<float>(Con)/static_cast<float>(FullCon));
|
||||
}
|
||||
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(*pMeshInstance, C4MeshDenumeratorFactory), "Mesh"));
|
||||
|
|
|
@ -45,12 +45,13 @@ namespace
|
|||
// Helper to sort faces for FaceOrdering
|
||||
struct StdMeshInstanceFaceOrderingCmpPred
|
||||
{
|
||||
const StdSubMeshInstance& m_inst;
|
||||
const StdMeshVertex* m_vertices;
|
||||
StdSubMeshInstance::FaceOrdering m_face_ordering;
|
||||
const StdMeshMatrix& m_global_trans;
|
||||
|
||||
StdMeshInstanceFaceOrderingCmpPred(const StdMeshInstance& mesh_inst, const StdSubMeshInstance& sub_inst, const StdMeshMatrix& global_trans):
|
||||
m_inst(sub_inst), m_global_trans(global_trans)
|
||||
StdMeshInstanceFaceOrderingCmpPred(const StdMeshInstance& mesh_inst, const StdSubMeshInstance& sub_inst,
|
||||
StdSubMeshInstance::FaceOrdering face_ordering, const StdMeshMatrix& global_trans):
|
||||
m_face_ordering(face_ordering), m_global_trans(global_trans)
|
||||
{
|
||||
if(sub_inst.GetNumVertices() > 0)
|
||||
m_vertices = &sub_inst.GetVertices()[0];
|
||||
|
@ -77,7 +78,7 @@ namespace
|
|||
int compare(const StdMeshFace& face1, const StdMeshFace& face2) const
|
||||
{
|
||||
// TODO: Need to apply attach matrix in case of attached meshes
|
||||
switch (m_inst.GetFaceOrdering())
|
||||
switch (m_face_ordering)
|
||||
{
|
||||
case StdSubMeshInstance::FO_Fixed:
|
||||
assert(false);
|
||||
|
@ -95,7 +96,7 @@ namespace
|
|||
float z1 = std::max(std::max(z11, z12), z13);
|
||||
float z2 = std::max(std::max(z21, z22), z23);
|
||||
|
||||
if (m_inst.GetFaceOrdering() == StdSubMeshInstance::FO_FarthestToNearest)
|
||||
if (m_face_ordering == StdSubMeshInstance::FO_FarthestToNearest)
|
||||
return (z1 < z2 ? -1 : (z1 > z2 ? +1 : 0));
|
||||
else
|
||||
return (z2 < z1 ? -1 : (z2 > z1 ? +1 : 0));
|
||||
|
@ -421,17 +422,39 @@ void StdMesh::PostInit()
|
|||
std::sort(SubMeshes.begin(), SubMeshes.end(), StdMeshSubMeshVisibilityCmpPred());
|
||||
}
|
||||
|
||||
StdSubMeshInstance::StdSubMeshInstance(const StdSubMesh& submesh):
|
||||
Vertices(submesh.GetNumVertices()), Faces(submesh.GetNumFaces()),
|
||||
StdSubMeshInstance::StdSubMeshInstance(StdMeshInstance& instance, const StdSubMesh& submesh, float completion):
|
||||
Vertices(submesh.GetNumVertices()),
|
||||
Material(NULL), CurrentFaceOrdering(FO_Fixed)
|
||||
{
|
||||
// Copy initial Vertices/Faces
|
||||
for (unsigned int i = 0; i < submesh.GetNumVertices(); ++i)
|
||||
Vertices[i] = submesh.GetVertex(i);
|
||||
LoadFacesForCompletion(instance, submesh, completion);
|
||||
|
||||
SetMaterial(submesh.GetMaterial());
|
||||
}
|
||||
|
||||
void StdSubMeshInstance::LoadFacesForCompletion(StdMeshInstance& instance, const StdSubMesh& submesh, float completion)
|
||||
{
|
||||
// First: Copy all faces
|
||||
Faces.resize(submesh.GetNumFaces());
|
||||
for (unsigned int i = 0; i < submesh.GetNumFaces(); ++i)
|
||||
Faces[i] = submesh.GetFace(i);
|
||||
|
||||
SetMaterial(submesh.GetMaterial());
|
||||
if(completion < 1.0f)
|
||||
{
|
||||
// Second: Order by Y position. StdMeshInstanceFaceOrderingCmpPred orders by Z position,
|
||||
// however we can simply give an appropriate transformation matrix to the face ordering.
|
||||
// At this point, all vertices are in the OGRE coordinate frame, and Z in OGRE equals
|
||||
// Y in Clonk, so we are fine without additional transformation.
|
||||
StdMeshInstanceFaceOrderingCmpPred pred(instance, *this, FO_FarthestToNearest, StdMeshMatrix::Identity());
|
||||
g_pred = &pred;
|
||||
StdMesh_tim_sort(&Faces[0], Faces.size());
|
||||
g_pred = NULL;
|
||||
|
||||
// Third: Only use the first few ones
|
||||
Faces.resize(static_cast<unsigned int>(completion * submesh.GetNumFaces() + 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
void StdSubMeshInstance::SetMaterial(const StdMeshMaterial& material)
|
||||
|
@ -702,8 +725,8 @@ void StdMeshInstance::AttachedMesh::DenumeratePointers()
|
|||
ChildDenumerator->DenumeratePointers(this);
|
||||
}
|
||||
|
||||
StdMeshInstance::StdMeshInstance(const StdMesh& mesh):
|
||||
Mesh(&mesh), SharedVertices(mesh.GetSharedVertices().size()),
|
||||
StdMeshInstance::StdMeshInstance(const StdMesh& mesh, float completion):
|
||||
Mesh(&mesh), SharedVertices(mesh.GetSharedVertices().size()), Completion(completion),
|
||||
BoneTransforms(Mesh->GetNumBones(), StdMeshMatrix::Identity()),
|
||||
SubMeshInstances(Mesh->GetNumSubMeshes()), AttachParent(NULL),
|
||||
BoneTransformsDirty(false)
|
||||
|
@ -716,7 +739,7 @@ StdMeshInstance::StdMeshInstance(const StdMesh& mesh):
|
|||
for (unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i)
|
||||
{
|
||||
const StdSubMesh& submesh = Mesh->GetSubMesh(i);
|
||||
SubMeshInstances[i] = new StdSubMeshInstance(submesh);
|
||||
SubMeshInstances[i] = new StdSubMeshInstance(*this, submesh, completion);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -763,6 +786,16 @@ void StdMeshInstance::SetFaceOrderingForClrModulation(uint32_t clrmod)
|
|||
(*iter)->Child->SetFaceOrderingForClrModulation(clrmod);
|
||||
}
|
||||
|
||||
void StdMeshInstance::SetCompletion(float completion)
|
||||
{
|
||||
Completion = completion;
|
||||
|
||||
// TODO: Load all submesh faces and then determine the ones to use from the
|
||||
// full pool.
|
||||
for(unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i)
|
||||
SubMeshInstances[i]->LoadFacesForCompletion(*this, Mesh->GetSubMesh(i), completion);
|
||||
}
|
||||
|
||||
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight)
|
||||
{
|
||||
const StdMeshAnimation* animation = Mesh->GetAnimationByName(animation_name);
|
||||
|
@ -976,7 +1009,7 @@ void StdMeshInstance::ExecuteAnimation(float dt)
|
|||
|
||||
StdMeshInstance::AttachedMesh* StdMeshInstance::AttachMesh(const StdMesh& mesh, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation, uint32_t flags)
|
||||
{
|
||||
StdMeshInstance* instance = new StdMeshInstance(mesh);
|
||||
StdMeshInstance* instance = new StdMeshInstance(mesh, 1.0f);
|
||||
AttachedMesh* attach = AttachMesh(*instance, denumerator, parent_bone, child_bone, transformation, flags, true);
|
||||
if (!attach) { delete instance; delete denumerator; return NULL; }
|
||||
return attach;
|
||||
|
@ -1147,7 +1180,7 @@ void StdMeshInstance::ReorderFaces(StdMeshMatrix* global_trans)
|
|||
StdSubMeshInstance& inst = *SubMeshInstances[i];
|
||||
if(inst.CurrentFaceOrdering != StdSubMeshInstance::FO_Fixed)
|
||||
{
|
||||
StdMeshInstanceFaceOrderingCmpPred pred(*this, inst, global_trans ? *global_trans : StdMeshMatrix::Identity());
|
||||
StdMeshInstanceFaceOrderingCmpPred pred(*this, inst, inst.CurrentFaceOrdering, global_trans ? *global_trans : StdMeshMatrix::Identity());
|
||||
|
||||
// The usage of timsort instead of std::sort at this point is twofold.
|
||||
// First, it's faster in our case where the array is already sorted in
|
||||
|
|
|
@ -205,7 +205,8 @@ public:
|
|||
FO_NearestToFarthest
|
||||
};
|
||||
|
||||
StdSubMeshInstance(const StdSubMesh& submesh);
|
||||
StdSubMeshInstance(class StdMeshInstance& instance, const StdSubMesh& submesh, float completion);
|
||||
void LoadFacesForCompletion(class StdMeshInstance& instance, const StdSubMesh& submesh, float completion);
|
||||
|
||||
// Get vertex of instance, with current animation applied. This needs to
|
||||
// go elsewhere if/when we want to calculate this on the hardware.
|
||||
|
@ -271,7 +272,7 @@ class StdMeshInstance
|
|||
friend class StdMeshMaterialUpdate;
|
||||
friend class StdMeshUpdate;
|
||||
public:
|
||||
StdMeshInstance(const StdMesh& mesh);
|
||||
StdMeshInstance(const StdMesh& mesh, float completion = 1.0f);
|
||||
~StdMeshInstance();
|
||||
|
||||
typedef StdSubMeshInstance::FaceOrdering FaceOrdering;
|
||||
|
@ -478,13 +479,17 @@ public:
|
|||
void SetFaceOrdering(FaceOrdering ordering);
|
||||
void SetFaceOrderingForClrModulation(uint32_t clrmod);
|
||||
|
||||
const std::vector<StdMeshVertex>& GetSharedVertices() const { return SharedVertices; }
|
||||
size_t GetNumSharedVertices() const { return SharedVertices.size(); }
|
||||
|
||||
// Set completion of the mesh. For incompleted meshes not all faces will be available.
|
||||
void SetCompletion(float completion);
|
||||
float GetCompletion() const { return Completion; }
|
||||
|
||||
AnimationNode* PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight);
|
||||
AnimationNode* PlayAnimation(const StdMeshAnimation& animation, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight);
|
||||
void StopAnimation(AnimationNode* node);
|
||||
|
||||
const std::vector<StdMeshVertex>& GetSharedVertices() const { return SharedVertices; }
|
||||
size_t GetNumSharedVertices() const { return SharedVertices.size(); }
|
||||
|
||||
AnimationNode* GetAnimationNodeByNumber(unsigned int number);
|
||||
AnimationNode* GetRootAnimationForSlot(int slot);
|
||||
// child bone transforms are dirty (saves matrix inversion for unanimated attach children).
|
||||
|
@ -550,6 +555,8 @@ protected:
|
|||
|
||||
const StdMesh* Mesh;
|
||||
|
||||
float Completion; // NoSave
|
||||
|
||||
std::vector<StdMeshVertex> SharedVertices;
|
||||
|
||||
AnimationNodeList AnimationNodes; // for simple lookup of animation nodes by their unique number
|
||||
|
|
|
@ -104,7 +104,7 @@ void StdMeshUpdate::Update(StdMeshInstance* instance, const StdMesh& new_mesh) c
|
|||
delete instance->SubMeshInstances[i];
|
||||
instance->SubMeshInstances.resize(new_mesh.GetNumSubMeshes());
|
||||
for (unsigned int i = 0; i < instance->SubMeshInstances.size(); ++i)
|
||||
instance->SubMeshInstances[i] = new StdSubMeshInstance(new_mesh.GetSubMesh(i));
|
||||
instance->SubMeshInstances[i] = new StdSubMeshInstance(*instance, new_mesh.GetSubMesh(i), instance->GetCompletion());
|
||||
|
||||
// Update child bone of attach parent. If the bone does not exist anymore
|
||||
// in the updated mesh, then detach the mesh from its parent
|
||||
|
|
|
@ -819,19 +819,28 @@ namespace
|
|||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
|
||||
glFrontFace(parity ? GL_CW : GL_CCW);
|
||||
|
||||
switch (pass.CullHardware)
|
||||
if(mesh_instance.GetCompletion() < 1.0f)
|
||||
{
|
||||
case StdMeshMaterialPass::CH_Clockwise:
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
break;
|
||||
case StdMeshMaterialPass::CH_CounterClockwise:
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
break;
|
||||
case StdMeshMaterialPass::CH_None:
|
||||
// Backfaces might be visible when completion is < 1.0f since front
|
||||
// faces might be omitted.
|
||||
glDisable(GL_CULL_FACE);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pass.CullHardware)
|
||||
{
|
||||
case StdMeshMaterialPass::CH_Clockwise:
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
break;
|
||||
case StdMeshMaterialPass::CH_CounterClockwise:
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
break;
|
||||
case StdMeshMaterialPass::CH_None:
|
||||
glDisable(GL_CULL_FACE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Overwrite blend mode with default alpha blending when alpha in clrmod
|
||||
|
|
Loading…
Reference in New Issue