Draw only partial set of faces for buildings in construction

rope
Armin Burgmeier 2012-02-26 01:09:42 +01:00
parent de67769065
commit 7f5f916e76
7 changed files with 88 additions and 37 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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"));

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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