OpenClonk
StdMeshInstance Class Reference

#include <StdMesh.h>

Collaboration diagram for StdMeshInstance:
[legend]

Classes

class  AttachedMesh
 
class  SerializableValueProvider
 

Public Types

enum  AttachMeshFlags { AM_None = 0 , AM_DrawBefore = 1 << 0 , AM_MatchSkeleton = 1 << 1 }
 
typedef StdMeshInstanceAnimationNode AnimationNode
 
typedef StdSubMeshInstance::FaceOrdering FaceOrdering
 
typedef StdMeshInstanceValueProvider ValueProvider
 
typedef std::vector< AttachedMesh * > AttachedMeshList
 
typedef AttachedMeshList::const_iterator AttachedMeshIter
 

Public Member Functions

 StdMeshInstance (const StdMesh &mesh, float completion=1.0f)
 
 ~StdMeshInstance ()
 
void SetFaceOrdering (FaceOrdering ordering)
 
void SetFaceOrderingForClrModulation (uint32_t clrmod)
 
const std::vector< StdMeshVertex > & GetSharedVertices () const
 
size_t GetNumSharedVertices () const
 
void SetCompletion (float completion)
 
float GetCompletion () const
 
AnimationNodePlayAnimation (const StdStrBuf &animation_name, int slot, AnimationNode *sibling, ValueProvider *position, ValueProvider *weight, bool stop_previous_animation)
 
AnimationNodePlayAnimation (const StdMeshAnimation &animation, int slot, AnimationNode *sibling, ValueProvider *position, ValueProvider *weight, bool stop_previous_animation)
 
AnimationNodePlayAnimation (const StdMeshBone *bone, const StdMeshTransformation &trans, int slot, AnimationNode *sibling, ValueProvider *weight, bool stop_previous_animation)
 
void StopAnimation (AnimationNode *node)
 
AnimationNodeGetAnimationNodeByNumber (unsigned int number)
 
AnimationNodeGetRootAnimationForSlot (int slot)
 
void SetAnimationPosition (AnimationNode *node, ValueProvider *position)
 
void SetAnimationBoneTransform (AnimationNode *node, const StdMeshTransformation &trans)
 
void SetAnimationWeight (AnimationNode *node, ValueProvider *weight)
 
void ExecuteAnimation (float dt)
 
AttachedMeshAttachMesh (const StdMesh &mesh, AttachedMesh::Denumerator *denumerator, const StdStrBuf &parent_bone, const StdStrBuf &child_bone, const StdMeshMatrix &transformation=StdMeshMatrix::Identity(), uint32_t flags=AM_None, unsigned int attach_number=0)
 
AttachedMeshAttachMesh (StdMeshInstance &instance, AttachedMesh::Denumerator *denumerator, const StdStrBuf &parent_bone, const StdStrBuf &child_bone, const StdMeshMatrix &transformation=StdMeshMatrix::Identity(), uint32_t flags=AM_None, bool own_child=false, unsigned int attach_number=0)
 
bool DetachMesh (unsigned int number)
 
AttachedMeshGetAttachedMeshByNumber (unsigned int number) const
 
AttachedMeshIter AttachedMeshesBegin () const
 
AttachedMeshIter AttachedMeshesEnd () const
 
AttachedMeshGetAttachParent () const
 
size_t GetNumSubMeshes () const
 
StdSubMeshInstanceGetSubMesh (size_t i)
 
const StdSubMeshInstanceGetSubMesh (size_t i) const
 
const StdSubMeshInstanceGetSubMeshOrdered (size_t i) const
 
void SetMaterial (size_t i, const StdMeshMaterial &material)
 
const StdMeshMatrixGetBoneTransform (size_t i) const
 
size_t GetBoneCount () const
 
bool UpdateBoneTransforms ()
 
void ReorderFaces (StdMeshMatrix *global_trans)
 
void CompileFunc (StdCompiler *pComp, AttachedMesh::DenumeratorFactoryFunc Factory)
 
void DenumeratePointers ()
 
void ClearPointers (class C4Object *pObj)
 
const StdMeshGetMesh () const
 
GLuint GetIBO () const
 
unsigned int GetVAOID () const
 

Protected Types

typedef std::vector< AnimationNode * > AnimationNodeList
 

Protected Member Functions

void UpdateIBO ()
 
AttachedMeshAttachMeshImpl (StdMeshInstance &instance, AttachedMesh::Denumerator *denumerator, const StdStrBuf &parent_bone, const StdStrBuf &child_bone, const StdMeshMatrix &transformation, uint32_t flags, bool own_child, unsigned int new_attach_number)
 
AnimationNodeList::iterator GetStackIterForSlot (int slot, bool create)
 
void InsertAnimationNode (AnimationNode *node, int slot, AnimationNode *sibling, ValueProvider *weight, bool stop_previous_animation)
 
bool ExecuteAnimationNode (AnimationNode *node)
 
void ApplyBoneTransformToVertices (const std::vector< StdSubMesh::Vertex > &mesh_vertices, std::vector< StdMeshVertex > &instance_vertices)
 
void SetBoneTransformsDirty (bool value)
 

Static Protected Member Functions

template<typename IteratorType , typename FuncObj >
static bool ScanAttachTree (IteratorType begin, IteratorType end, const FuncObj &obj)
 

Protected Attributes

const StdMeshMesh
 
float Completion
 
AnimationNodeList AnimationNodes
 
AnimationNodeList AnimationStack
 
std::vector< StdMeshMatrixBoneTransforms
 
std::vector< StdSubMeshInstance * > SubMeshInstances
 
std::vector< StdSubMeshInstance * > SubMeshInstancesOrdered
 
std::vector< AttachedMesh * > AttachChildren
 
AttachedMeshAttachParent
 
bool BoneTransformsDirty
 
GLuint ibo
 
unsigned int vaoid
 

Friends

class StdMeshMaterialUpdate
 
class StdMeshAnimationUpdate
 
class StdMeshUpdate
 

Detailed Description

Definition at line 393 of file StdMesh.h.

Member Typedef Documentation

◆ AnimationNode

◆ AnimationNodeList

typedef std::vector<AnimationNode*> StdMeshInstance::AnimationNodeList
protected

Definition at line 639 of file StdMesh.h.

◆ AttachedMeshIter

typedef AttachedMeshList::const_iterator StdMeshInstance::AttachedMeshIter

Definition at line 544 of file StdMesh.h.

◆ AttachedMeshList

Definition at line 543 of file StdMesh.h.

◆ FaceOrdering

◆ ValueProvider

Member Enumeration Documentation

◆ AttachMeshFlags

Enumerator
AM_None 
AM_DrawBefore 
AM_MatchSkeleton 

Definition at line 405 of file StdMesh.h.

405  {
406  AM_None = 0,
407  AM_DrawBefore = 1 << 0,
408  AM_MatchSkeleton = 1 << 1
409  };

Constructor & Destructor Documentation

◆ StdMeshInstance()

StdMeshInstance::StdMeshInstance ( const StdMesh mesh,
float  completion = 1.0f 
)

Definition at line 1072 of file StdMesh.cpp.

1072  :
1073  Mesh(&mesh), Completion(completion),
1076  BoneTransformsDirty(false)
1077 #ifndef USE_CONSOLE
1078  , ibo(0), vaoid(0)
1079 #endif
1080 {
1081  // Create submesh instances
1082  for (unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i)
1083  {
1084  const StdSubMesh& submesh = Mesh->GetSubMesh(i);
1085  SubMeshInstances[i] = new StdSubMeshInstance(*this, submesh, completion);
1086  }
1087 
1088  // copy, order is fine at the moment since only default materials are used.
1090 }
const StdSubMesh & GetSubMesh(size_t i) const
Definition: StdMesh.h:198
size_t GetNumSubMeshes() const
Definition: StdMesh.h:199
const StdMeshSkeleton & GetSkeleton() const
Definition: StdMesh.h:203
std::vector< StdSubMeshInstance * > SubMeshInstances
Definition: StdMesh.h:655
std::vector< StdSubMeshInstance * > SubMeshInstancesOrdered
Definition: StdMesh.h:656
GLuint ibo
Definition: StdMesh.h:670
std::vector< StdMeshMatrix > BoneTransforms
Definition: StdMesh.h:653
unsigned int vaoid
Definition: StdMesh.h:671
bool BoneTransformsDirty
Definition: StdMesh.h:663
AttachedMesh * AttachParent
Definition: StdMesh.h:661
float Completion
Definition: StdMesh.h:649
const StdMesh * Mesh
Definition: StdMesh.h:647
static StdMeshMatrix Identity()
size_t GetNumBones() const
Definition: StdMesh.h:117

References StdMesh::GetNumSubMeshes(), StdMesh::GetSubMesh(), Mesh, SubMeshInstances, and SubMeshInstancesOrdered.

Referenced by AttachMesh().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~StdMeshInstance()

StdMeshInstance::~StdMeshInstance ( )

Definition at line 1092 of file StdMesh.cpp.

1093 {
1094 #ifndef USE_CONSOLE
1095  if (ibo) glDeleteBuffers(1, &ibo);
1096  if (vaoid) pGL->FreeVAOID(vaoid);
1097 #endif
1098 
1099  // If we are attached then detach from parent
1100  if (AttachParent)
1102 
1103  // Remove all attach children
1104  while (!AttachChildren.empty())
1105  DetachMesh(AttachChildren.back()->Number);
1106 
1107  while (!AnimationStack.empty())
1108  StopAnimation(AnimationStack.front());
1109  assert(AnimationNodes.empty());
1110 
1111  // Delete submeshes
1112  for (auto & SubMeshInstance : SubMeshInstances)
1113  {
1114  delete SubMeshInstance;
1115  }
1116 }
CStdGL * pGL
Definition: C4DrawGL.cpp:907
void FreeVAOID(unsigned int vaoid)
Definition: C4DrawGL.cpp:969
StdMeshInstance * Parent
Definition: StdMesh.h:510
AnimationNodeList AnimationNodes
Definition: StdMesh.h:651
AnimationNodeList AnimationStack
Definition: StdMesh.h:652
bool DetachMesh(unsigned int number)
Definition: StdMesh.cpp:1395
void StopAnimation(AnimationNode *node)
Definition: StdMesh.cpp:1190
std::vector< AttachedMesh * > AttachChildren
Definition: StdMesh.h:660

References AnimationNodes, AnimationStack, AttachChildren, AttachParent, DetachMesh(), CStdGL::FreeVAOID(), ibo, StdMeshInstance::AttachedMesh::Number, StdMeshInstance::AttachedMesh::Parent, pGL, StopAnimation(), SubMeshInstances, and vaoid.

Here is the call graph for this function:

Member Function Documentation

◆ ApplyBoneTransformToVertices()

void StdMeshInstance::ApplyBoneTransformToVertices ( const std::vector< StdSubMesh::Vertex > &  mesh_vertices,
std::vector< StdMeshVertex > &  instance_vertices 
)
protected

◆ AttachedMeshesBegin()

AttachedMeshIter StdMeshInstance::AttachedMeshesBegin ( ) const
inline

Definition at line 584 of file StdMesh.h.

584 { return AttachChildren.begin(); }

References AttachChildren.

Referenced by StdMeshUpdate::Update().

Here is the caller graph for this function:

◆ AttachedMeshesEnd()

AttachedMeshIter StdMeshInstance::AttachedMeshesEnd ( ) const
inline

Definition at line 585 of file StdMesh.h.

585 { return AttachChildren.end(); }

References AttachChildren.

Referenced by StdMeshUpdate::Update().

Here is the caller graph for this function:

◆ AttachMesh() [1/2]

StdMeshInstance::AttachedMesh * StdMeshInstance::AttachMesh ( const StdMesh mesh,
AttachedMesh::Denumerator denumerator,
const StdStrBuf parent_bone,
const StdStrBuf child_bone,
const StdMeshMatrix transformation = StdMeshMatrix::Identity(),
uint32_t  flags = AM_None,
unsigned int  attach_number = 0 
)

Definition at line 1333 of file StdMesh.cpp.

1334 {
1335  std::unique_ptr<AttachedMesh::Denumerator> auto_denumerator(denumerator);
1336 
1337  StdMeshInstance* instance = new StdMeshInstance(mesh, 1.0f);
1338  AttachedMesh* attach = AttachMesh(*instance, auto_denumerator.release(), parent_bone, child_bone, transformation, flags, true, attach_number);
1339  if (!attach) { delete instance; return nullptr; }
1340  return attach;
1341 }
StdMeshInstance(const StdMesh &mesh, float completion=1.0f)
Definition: StdMesh.cpp:1072
AttachedMesh * AttachMesh(const StdMesh &mesh, AttachedMesh::Denumerator *denumerator, const StdStrBuf &parent_bone, const StdStrBuf &child_bone, const StdMeshMatrix &transformation=StdMeshMatrix::Identity(), uint32_t flags=AM_None, unsigned int attach_number=0)
Definition: StdMesh.cpp:1333

References StdMeshInstance().

Here is the call graph for this function:

◆ AttachMesh() [2/2]

StdMeshInstance::AttachedMesh * StdMeshInstance::AttachMesh ( StdMeshInstance instance,
AttachedMesh::Denumerator denumerator,
const StdStrBuf parent_bone,
const StdStrBuf child_bone,
const StdMeshMatrix transformation = StdMeshMatrix::Identity(),
uint32_t  flags = AM_None,
bool  own_child = false,
unsigned int  attach_number = 0 
)

Definition at line 1343 of file StdMesh.cpp.

1344 {
1345  std::unique_ptr<AttachedMesh::Denumerator> auto_denumerator(denumerator);
1346 
1347  // Owned attach children must be set via the topmost instance, to ensure
1348  // attach number uniqueness.
1349  if (AttachParent && AttachParent->OwnChild) return nullptr;
1350 
1351  // Find free index.
1352  unsigned int number = 0;
1353  ScanAttachTree(AttachChildren.begin(), AttachChildren.end(), [&number](AttachedMeshList::const_iterator iter) { number = std::max(number, (*iter)->Number); return true; });
1354  number += 1; // One above highest
1355 
1356  StdMeshInstance* direct_parent = this;
1357  if (attach_number != 0)
1358  {
1359  AttachedMesh* attach = GetAttachedMeshByNumber(attach_number);
1360  if (attach == nullptr) return nullptr;
1361  direct_parent = attach->Child;
1362  }
1363 
1364  return direct_parent->AttachMeshImpl(instance, auto_denumerator.release(), parent_bone, child_bone, transformation, flags, own_child, number);
1365 }
static bool ScanAttachTree(IteratorType begin, IteratorType end, const FuncObj &obj)
Definition: StdMesh.cpp:1702
AttachedMesh * GetAttachedMeshByNumber(unsigned int number) const
Definition: StdMesh.cpp:1419
AttachedMesh * AttachMeshImpl(StdMeshInstance &instance, AttachedMesh::Denumerator *denumerator, const StdStrBuf &parent_bone, const StdStrBuf &child_bone, const StdMeshMatrix &transformation, uint32_t flags, bool own_child, unsigned int new_attach_number)
Definition: StdMesh.cpp:1367

References AttachChildren, AttachMeshImpl(), AttachParent, StdMeshInstance::AttachedMesh::Child, GetAttachedMeshByNumber(), StdMeshInstance::AttachedMesh::OwnChild, and ScanAttachTree().

Here is the call graph for this function:

◆ AttachMeshImpl()

StdMeshInstance::AttachedMesh * StdMeshInstance::AttachMeshImpl ( StdMeshInstance instance,
AttachedMesh::Denumerator denumerator,
const StdStrBuf parent_bone,
const StdStrBuf child_bone,
const StdMeshMatrix transformation,
uint32_t  flags,
bool  own_child,
unsigned int  new_attach_number 
)
protected

Definition at line 1367 of file StdMesh.cpp.

1368 {
1369  std::unique_ptr<AttachedMesh::Denumerator> auto_denumerator(denumerator);
1370 
1371  // We don't allow an instance to be attached to multiple parent instances for now
1372  if (instance.AttachParent) return nullptr;
1373 
1374  // Make sure there are no cyclic attachments
1375  for (StdMeshInstance* Parent = this; Parent->AttachParent != nullptr; Parent = Parent->AttachParent->Parent)
1376  if (Parent == &instance)
1377  return nullptr;
1378 
1379  const StdMeshBone* parent_bone_obj = Mesh->GetSkeleton().GetBoneByName(parent_bone);
1380  const StdMeshBone* child_bone_obj = instance.Mesh->GetSkeleton().GetBoneByName(child_bone);
1381  if (!parent_bone_obj || !child_bone_obj) return nullptr;
1382 
1383  AttachedMesh* attach = new AttachedMesh(new_attach_number, this, &instance, own_child, auto_denumerator.release(), parent_bone_obj->Index, child_bone_obj->Index, transformation, flags);
1384  instance.AttachParent = attach;
1385 
1386  // If DrawInFront is set then sort before others so that drawing order is easy
1387  if(flags & AM_DrawBefore)
1388  AttachChildren.insert(AttachChildren.begin(), attach);
1389  else
1390  AttachChildren.insert(AttachChildren.end(), attach);
1391 
1392  return attach;
1393 }
unsigned int Index
Definition: StdMesh.h:32
const StdMeshBone * GetBoneByName(const StdStrBuf &name) const
Definition: StdMesh.cpp:388

References AM_DrawBefore, AttachChildren, AttachParent, StdMeshSkeleton::GetBoneByName(), StdMesh::GetSkeleton(), StdMeshBone::Index, Mesh, and StdMeshInstance::AttachedMesh::Parent.

Referenced by AttachMesh().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ClearPointers()

void StdMeshInstance::ClearPointers ( class C4Object pObj)

Definition at line 1686 of file StdMesh.cpp.

1687 {
1688  for(auto & AnimationNode : AnimationNodes)
1689  if(AnimationNode)
1691 
1692  std::vector<unsigned int> Removal;
1693  for(auto & i : AttachChildren)
1694  if(!i->ClearPointers(pObj))
1695  Removal.push_back(i->Number);
1696 
1697  for(unsigned int i : Removal)
1698  DetachMesh(i);
1699 }
void ClearPointers(class C4Object *pObj)
Definition: StdMesh.cpp:953
StdMeshInstanceAnimationNode AnimationNode
Definition: StdMesh.h:399

References AnimationNodes, AttachChildren, StdMeshInstanceAnimationNode::ClearPointers(), and DetachMesh().

Referenced by C4Object::ClearPointers().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CompileFunc()

void StdMeshInstance::CompileFunc ( StdCompiler pComp,
AttachedMesh::DenumeratorFactoryFunc  Factory 
)

Definition at line 1578 of file StdMesh.cpp.

1579 {
1580  if(pComp->isDeserializer())
1581  {
1582  // Only initially created instances can be compiled
1583  assert(!AttachParent);
1584  assert(AttachChildren.empty());
1585  assert(AnimationStack.empty());
1586  SetBoneTransformsDirty(true);
1587 
1588  bool valid;
1589  pComp->Value(mkNamingAdapt(valid, "Valid"));
1590  if(!valid) pComp->excCorrupt("Mesh instance is invalid");
1591 
1592  int32_t iSubMeshCnt;
1593  pComp->Value(mkNamingCountAdapt(iSubMeshCnt, "SubMesh"));
1594  if(static_cast<uint32_t>(iSubMeshCnt) != SubMeshInstances.size())
1595  pComp->excCorrupt("Invalid number of submeshes");
1596  for(int32_t i = 0; i < iSubMeshCnt; ++i)
1597  pComp->Value(mkNamingAdapt(*SubMeshInstances[i], "SubMesh"));
1598 #ifndef USE_CONSOLE
1599  // The sorting predicate depends on having a gfx implementation.
1600  std::stable_sort(SubMeshInstancesOrdered.begin(), SubMeshInstancesOrdered.end(), StdMeshSubMeshInstanceVisibilityCmpPred());
1601 #endif
1602 
1603  int32_t iAnimCnt = AnimationStack.size();
1604  pComp->Value(mkNamingCountAdapt(iAnimCnt, "AnimationNode"));
1605 
1606  for(int32_t i = 0; i < iAnimCnt; ++i)
1607  {
1608  AnimationNode* node = nullptr;
1609  pComp->Value(mkParAdapt(mkNamingPtrAdapt(node, "AnimationNode"), Mesh));
1610  AnimationNodeList::iterator iter = GetStackIterForSlot(node->Slot, true);
1611  if(*iter != nullptr) { delete node; pComp->excCorrupt("Duplicate animation slot index"); }
1612  *iter = node;
1613 
1614  // Add nodes into lookup table
1615  std::vector<AnimationNode*> nodes(1, node);
1616  while(!nodes.empty())
1617  {
1618  node = nodes.back();
1619  nodes.erase(nodes.end()-1);
1620 
1621  if (AnimationNodes.size() <= node->Number)
1622  AnimationNodes.resize(node->Number+1);
1623  if(AnimationNodes[node->Number] != nullptr) pComp->excCorrupt("Duplicate animation node number");
1624  AnimationNodes[node->Number] = node;
1625 
1626  if(node->Type == AnimationNode::LinearInterpolationNode)
1627  {
1628  nodes.push_back(node->LinearInterpolation.ChildLeft);
1629  nodes.push_back(node->LinearInterpolation.ChildRight);
1630  }
1631  }
1632  }
1633 
1634  int32_t iAttachedCnt;
1635  pComp->Value(mkNamingCountAdapt(iAttachedCnt, "Attached"));
1636 
1637  for(int32_t i = 0; i < iAttachedCnt; ++i)
1638  {
1639  AttachChildren.push_back(new AttachedMesh);
1640  AttachedMesh* attach = AttachChildren.back();
1641 
1642  attach->Parent = this;
1643  pComp->Value(mkNamingAdapt(mkParAdapt(*attach, Factory), "Attached"));
1644  }
1645  }
1646  else
1647  {
1648  // Write something to make sure that the parent
1649  // named section ([Mesh] or [ChildInstance]) is written.
1650  // StdCompilerIni does not make a difference between
1651  // non-existing and empty named sections.
1652  bool valid = true;
1653  pComp->Value(mkNamingAdapt(valid, "Valid"));
1654 
1655  int32_t iSubMeshCnt = SubMeshInstances.size();
1656  pComp->Value(mkNamingCountAdapt(iSubMeshCnt, "SubMesh"));
1657  for(int32_t i = 0; i < iSubMeshCnt; ++i)
1658  pComp->Value(mkNamingAdapt(*SubMeshInstances[i], "SubMesh"));
1659 
1660  int32_t iAnimCnt = AnimationStack.size();
1661  pComp->Value(mkNamingCountAdapt(iAnimCnt, "AnimationNode"));
1662 
1663  for(auto & iter : AnimationStack)
1664  pComp->Value(mkParAdapt(mkNamingPtrAdapt(iter, "AnimationNode"), Mesh));
1665 
1666  int32_t iAttachedCnt = AttachChildren.size();
1667  pComp->Value(mkNamingCountAdapt(iAttachedCnt, "Attached"));
1668 
1669  for(auto & i : AttachChildren)
1670  pComp->Value(mkNamingAdapt(mkParAdapt(*i, Factory), "Attached"));
1671  }
1672 }
StdPtrAdapt< T > mkNamingPtrAdapt(T *&rpObj, const char *szNaming)
Definition: StdAdaptors.h:636
StdParameterAdapt< T, P > mkParAdapt(T &&rObj, P &&rPar)
Definition: StdAdaptors.h:490
StdNamingCountAdapt< int_t > mkNamingCountAdapt(int_t &iCount, const char *szName)
Definition: StdAdaptors.h:1008
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
Definition: StdAdaptors.h:92
void excCorrupt(const char *szMessage,...)
Definition: StdCompiler.h:249
void Value(const T &rStruct)
Definition: StdCompiler.h:161
virtual bool isDeserializer()
Definition: StdCompiler.h:53
AnimationNodeList::iterator GetStackIterForSlot(int slot, bool create)
Definition: StdMesh.cpp:1718
void SetBoneTransformsDirty(bool value)
Definition: StdMesh.cpp:1893

References AnimationNodes, AnimationStack, AttachChildren, AttachParent, StdCompiler::excCorrupt(), GetStackIterForSlot(), StdCompiler::isDeserializer(), StdMeshInstanceAnimationNode::LinearInterpolationNode, Mesh, mkNamingAdapt(), mkNamingCountAdapt(), mkNamingPtrAdapt(), mkParAdapt(), StdMeshInstanceAnimationNode::Number, StdMeshInstance::AttachedMesh::Parent, SetBoneTransformsDirty(), StdMeshInstanceAnimationNode::Slot, SubMeshInstances, SubMeshInstancesOrdered, StdMeshInstanceAnimationNode::Type, and StdCompiler::Value().

Here is the call graph for this function:

◆ DenumeratePointers()

void StdMeshInstance::DenumeratePointers ( )

Definition at line 1674 of file StdMesh.cpp.

1675 {
1676  for(auto & AnimationNode : AnimationNodes)
1677  if(AnimationNode)
1679 
1680  for(auto & i : AttachChildren)
1681  {
1682  i->DenumeratePointers();
1683  }
1684 }

References AnimationNodes, AttachChildren, and StdMeshInstanceAnimationNode::DenumeratePointers().

Referenced by C4Object::Denumerate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ DetachMesh()

bool StdMeshInstance::DetachMesh ( unsigned int  number)

Definition at line 1395 of file StdMesh.cpp.

1396 {
1397  return !ScanAttachTree(AttachChildren.begin(), AttachChildren.end(), [number](AttachedMeshList::iterator iter)
1398  {
1399  if ((*iter)->Number == number)
1400  {
1401  AttachedMesh* attached = *iter;
1402 
1403  // Reset attach parent of child so it does not try
1404  // to detach itself on destruction.
1405  attached->Child->AttachParent = nullptr;
1406  attached->Parent->AttachChildren.erase(iter);
1407 
1408  delete attached;
1409 
1410  // Finish scan
1411  return false;
1412  }
1413 
1414  // Continue scan
1415  return true;
1416  });
1417 }

References AttachChildren, and ScanAttachTree().

Referenced by ClearPointers(), StdMeshUpdate::Update(), C4Object::UpdateGraphics(), and ~StdMeshInstance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ExecuteAnimation()

void StdMeshInstance::ExecuteAnimation ( float  dt)

Definition at line 1288 of file StdMesh.cpp.

1289 {
1290  // Iterate from the back since slots might be removed
1291  for (unsigned int i = AnimationStack.size(); i > 0; --i)
1294 
1295 #ifndef USE_CONSOLE
1296  // Update animated textures
1297  for (auto & SubMeshInstance : SubMeshInstances)
1298  {
1299  StdSubMeshInstance& submesh = *SubMeshInstance;
1300  const StdMeshMaterial& material = submesh.GetMaterial();
1301  const StdMeshMaterialTechnique& technique = material.Techniques[material.BestTechniqueIndex];
1302  for (unsigned int j = 0; j < submesh.PassData.size(); ++j)
1303  {
1304  StdSubMeshInstance::Pass& pass = submesh.PassData[j];
1305  for (unsigned int k = 0; k < pass.TexUnits.size(); ++k)
1306  {
1307  const StdMeshMaterialTextureUnit& texunit = technique.Passes[j].TextureUnits[k];
1308  StdSubMeshInstance::TexUnit& texunit_instance = submesh.PassData[j].TexUnits[k];
1309  if (texunit.HasFrameAnimation())
1310  {
1311  const unsigned int NumPhases = texunit.GetNumTextures();
1312  const float PhaseDuration = texunit.Duration / NumPhases;
1313 
1314  const float Position = texunit_instance.PhaseDelay + dt;
1315  const unsigned int AddPhases = static_cast<unsigned int>(Position / PhaseDuration);
1316 
1317  texunit_instance.Phase = (texunit_instance.Phase + AddPhases) % NumPhases;
1318  texunit_instance.PhaseDelay = Position - AddPhases * PhaseDuration;
1319  }
1320 
1321  if (texunit.HasTexCoordAnimation())
1322  texunit_instance.Position += dt;
1323  }
1324  }
1325  }
1326 #endif
1327 
1328  // Update animation for attached meshes
1329  for (auto & iter : AttachChildren)
1330  iter->Child->ExecuteAnimation(dt);
1331 }
bool ExecuteAnimationNode(AnimationNode *node)
Definition: StdMesh.cpp:1816
std::vector< StdMeshMaterialTechnique > Techniques
std::vector< StdMeshMaterialPass > Passes
std::vector< TexUnit > TexUnits
Definition: StdMesh.h:297
std::vector< Pass > PassData
Definition: StdMesh.h:300
const StdMeshMaterial & GetMaterial() const
Definition: StdMesh.h:270

References AnimationStack, AttachChildren, StdMeshMaterial::BestTechniqueIndex, StdMeshMaterialTextureUnit::Duration, ExecuteAnimationNode(), StdSubMeshInstance::GetMaterial(), StdMeshMaterialTextureUnit::GetNumTextures(), StdMeshMaterialTextureUnit::HasFrameAnimation(), StdMeshMaterialTextureUnit::HasTexCoordAnimation(), StdSubMeshInstance::PassData, StdMeshMaterialTechnique::Passes, StdSubMeshInstance::TexUnit::Phase, StdSubMeshInstance::TexUnit::PhaseDelay, StdSubMeshInstance::TexUnit::Position, StopAnimation(), SubMeshInstances, StdMeshMaterial::Techniques, and StdSubMeshInstance::Pass::TexUnits.

Referenced by C4Object::Execute().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ExecuteAnimationNode()

bool StdMeshInstance::ExecuteAnimationNode ( AnimationNode node)
protected

Definition at line 1816 of file StdMesh.cpp.

1817 {
1818  ValueProvider* provider = nullptr;
1819  C4Real min;
1820  C4Real max;
1821 
1822  switch (node->GetType())
1823  {
1825  provider = node->GetPositionProvider();
1826  min = Fix0;
1827  max = ftofix(node->GetAnimation()->Length);
1828  break;
1830  // No execution necessary
1831  return true;
1833  provider = node->GetWeightProvider();
1834  min = Fix0;
1835  max = itofix(1);
1836  break;
1837  default:
1838  assert(false);
1839  break;
1840  }
1841 
1842  assert(provider);
1843  const C4Real old_value = provider->Value;
1844 
1845  if (!provider->Execute())
1846  {
1847  if (node->GetType() == AnimationNode::LeafNode) return false;
1848 
1849  // Remove the child with less weight (normally weight reaches 0.0 or 1.0)
1850  if (node->GetWeight() > itofix(1, 2))
1851  {
1852  // Remove both children (by parent) if other wants to be deleted as well
1853  if (!ExecuteAnimationNode(node->GetRightChild())) return false;
1854  // Remove left child as it has less weight
1855  StopAnimation(node->LinearInterpolation.ChildLeft);
1856  }
1857  else
1858  {
1859  // Remove both children (by parent) if other wants to be deleted as well
1860  if (!ExecuteAnimationNode(node->GetLeftChild())) return false;
1861  // Remove right child as it has less weight
1862  StopAnimation(node->LinearInterpolation.ChildRight);
1863  }
1864  }
1865  else
1866  {
1867  if (provider->Value != old_value)
1868  {
1869  provider->Value = Clamp(provider->Value, min, max);
1870  SetBoneTransformsDirty(true);
1871  }
1872 
1873  if (node->GetType() == AnimationNode::LinearInterpolationNode)
1874  {
1875  const bool left_result = ExecuteAnimationNode(node->GetLeftChild());
1876  const bool right_result = ExecuteAnimationNode(node->GetRightChild());
1877 
1878  // Remove this node completely
1879  if (!left_result && !right_result)
1880  return false;
1881 
1882  // Note that either of this also removes node
1883  if (!left_result)
1884  StopAnimation(node->GetLeftChild());
1885  if (!right_result)
1886  StopAnimation(node->GetRightChild());
1887  }
1888  }
1889 
1890  return true;
1891 }
C4Fixed itofix(int32_t x)
Definition: C4Real.h:261
C4Fixed ftofix(float x)
Definition: C4Real.h:258
const C4Real Fix0
Definition: C4Real.h:312
T Clamp(T bval, T lbound, T rbound)
Definition: Standard.h:44
Definition: C4Real.h:59
StdMeshInstanceValueProvider ValueProvider
Definition: StdMesh.h:411

References Clamp(), StdMeshInstanceAnimationNode::CustomNode, StdMeshInstanceValueProvider::Execute(), Fix0, ftofix(), StdMeshInstanceAnimationNode::GetAnimation(), StdMeshInstanceAnimationNode::GetLeftChild(), StdMeshInstanceAnimationNode::GetPositionProvider(), StdMeshInstanceAnimationNode::GetRightChild(), StdMeshInstanceAnimationNode::GetType(), StdMeshInstanceAnimationNode::GetWeight(), StdMeshInstanceAnimationNode::GetWeightProvider(), itofix(), StdMeshInstanceAnimationNode::LeafNode, StdMeshAnimation::Length, StdMeshInstanceAnimationNode::LinearInterpolationNode, SetBoneTransformsDirty(), StopAnimation(), and StdMeshInstanceValueProvider::Value.

Referenced by ExecuteAnimation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetAnimationNodeByNumber()

StdMeshInstance::AnimationNode * StdMeshInstance::GetAnimationNodeByNumber ( unsigned int  number)

Definition at line 1247 of file StdMesh.cpp.

1248 {
1249  if (number >= AnimationNodes.size()) return nullptr;
1250  return AnimationNodes[number];
1251 }

References AnimationNodes.

◆ GetAttachedMeshByNumber()

StdMeshInstance::AttachedMesh * StdMeshInstance::GetAttachedMeshByNumber ( unsigned int  number) const

Definition at line 1419 of file StdMesh.cpp.

1420 {
1421  StdMeshInstance::AttachedMesh* result = nullptr;
1422 
1423  ScanAttachTree(AttachChildren.begin(), AttachChildren.end(), [number, &result](AttachedMeshList::const_iterator iter)
1424  {
1425  if ((*iter)->Number == number)
1426  {
1427  result = *iter;
1428  return false;
1429  }
1430 
1431  return true;
1432  });
1433 
1434  return result;
1435 }

References AttachChildren, and ScanAttachTree().

Referenced by AttachMesh().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetAttachParent()

AttachedMesh* StdMeshInstance::GetAttachParent ( ) const
inline

Definition at line 586 of file StdMesh.h.

586 { return AttachParent; }

References AttachParent.

Referenced by C4Object::Execute(), and C4Object::UpdateGraphics().

Here is the caller graph for this function:

◆ GetBoneCount()

size_t StdMeshInstance::GetBoneCount ( ) const

Definition at line 1463 of file StdMesh.cpp.

1464 {
1465  if ((AttachParent != nullptr) && (AttachParent->GetFlags() & AM_MatchSkeleton))
1466  return AttachParent->MatchedBoneInParentSkeleton.size();
1467  else
1468  return BoneTransforms.size();
1469 }
uint32_t GetFlags() const
Definition: StdMesh.h:519

References AM_MatchSkeleton, AttachParent, BoneTransforms, and StdMeshInstance::AttachedMesh::GetFlags().

Here is the call graph for this function:

◆ GetBoneTransform()

const StdMeshMatrix & StdMeshInstance::GetBoneTransform ( size_t  i) const

Definition at line 1446 of file StdMesh.cpp.

1447 {
1448  if ((AttachParent != nullptr) && (AttachParent->GetFlags() & AM_MatchSkeleton))
1449  {
1450  assert(i < AttachParent->MatchedBoneInParentSkeleton.size());
1451 
1452  int parent_bone_index = AttachParent->MatchedBoneInParentSkeleton[i];
1453 
1454  if (parent_bone_index > -1)
1455  {
1456  return AttachParent->Parent->BoneTransforms[i];
1457  }
1458  }
1459 
1460  return BoneTransforms[i];
1461 }

References AM_MatchSkeleton, AttachParent, BoneTransforms, StdMeshInstance::AttachedMesh::GetFlags(), and StdMeshInstance::AttachedMesh::Parent.

Referenced by UpdateBoneTransforms().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetCompletion()

float StdMeshInstance::GetCompletion ( ) const
inline

Definition at line 554 of file StdMesh.h.

554 { return Completion; }

References Completion.

Referenced by StdSubMeshInstance::SetFaceOrdering(), and StdMeshUpdate::Update().

Here is the caller graph for this function:

◆ GetIBO()

GLuint StdMeshInstance::GetIBO ( ) const
inline

Definition at line 625 of file StdMesh.h.

625 { return ibo ? ibo : Mesh->GetIBO(); }
GLuint GetIBO() const
Definition: StdMesh.h:213

References StdMesh::GetIBO(), ibo, and Mesh.

Here is the call graph for this function:

◆ GetMesh()

const StdMesh& StdMeshInstance::GetMesh ( ) const
inline

Definition at line 622 of file StdMesh.h.

622 { return *Mesh; }

References Mesh.

Referenced by StdMeshInstance::AttachedMesh::AttachedMesh(), C4Object::DrawFaceImpl(), CStdGL::PerformMesh(), StdMeshMaterialUpdate::Update(), StdMeshUpdate::Update(), and C4Object::UpdateGraphics().

Here is the caller graph for this function:

◆ GetNumSharedVertices()

size_t StdMeshInstance::GetNumSharedVertices ( ) const
inline

Definition at line 550 of file StdMesh.h.

550 { return GetSharedVertices().size(); }
const std::vector< StdMeshVertex > & GetSharedVertices() const
Definition: StdMesh.h:549

References GetSharedVertices().

Here is the call graph for this function:

◆ GetNumSubMeshes()

size_t StdMeshInstance::GetNumSubMeshes ( ) const
inline

Definition at line 588 of file StdMesh.h.

588 { return SubMeshInstances.size(); }

References SubMeshInstances.

◆ GetRootAnimationForSlot()

StdMeshInstance::AnimationNode * StdMeshInstance::GetRootAnimationForSlot ( int  slot)

Definition at line 1253 of file StdMesh.cpp.

1254 {
1255  AnimationNodeList::iterator iter = GetStackIterForSlot(slot, false);
1256  if (iter == AnimationStack.end()) return nullptr;
1257  return *iter;
1258 }

References AnimationStack, and GetStackIterForSlot().

Referenced by C4Object::CompileFunc(), and InsertAnimationNode().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetSharedVertices()

const std::vector<StdMeshVertex>& StdMeshInstance::GetSharedVertices ( ) const
inline

Definition at line 549 of file StdMesh.h.

549 { return Mesh->GetSharedVertices(); }
const std::vector< Vertex > & GetSharedVertices() const
Definition: StdMesh.h:201

References StdMesh::GetSharedVertices(), and Mesh.

Referenced by GetNumSharedVertices(), StdSubMeshInstance::LoadFacesForCompletion(), and ReorderFaces().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetStackIterForSlot()

StdMeshInstance::AnimationNodeList::iterator StdMeshInstance::GetStackIterForSlot ( int  slot,
bool  create 
)
protected

Definition at line 1718 of file StdMesh.cpp.

1719 {
1720  // TODO: bsearch
1721  for (AnimationNodeList::iterator iter = AnimationStack.begin(); iter != AnimationStack.end(); ++iter)
1722  {
1723  if ((*iter)->Slot == slot)
1724  {
1725  return iter;
1726  }
1727  else if ((*iter)->Slot > slot)
1728  {
1729  if (!create)
1730  return AnimationStack.end();
1731  else
1732  return AnimationStack.insert(iter, nullptr);
1733  }
1734  }
1735 
1736  if (!create)
1737  return AnimationStack.end();
1738  else
1739  return AnimationStack.insert(AnimationStack.end(), nullptr);
1740 }

References AnimationStack.

Referenced by CompileFunc(), GetRootAnimationForSlot(), InsertAnimationNode(), and StopAnimation().

Here is the caller graph for this function:

◆ GetSubMesh() [1/2]

StdSubMeshInstance& StdMeshInstance::GetSubMesh ( size_t  i)
inline

Definition at line 589 of file StdMesh.h.

589 { return *SubMeshInstances[i]; }

References SubMeshInstances.

◆ GetSubMesh() [2/2]

const StdSubMeshInstance& StdMeshInstance::GetSubMesh ( size_t  i) const
inline

Definition at line 590 of file StdMesh.h.

590 { return *SubMeshInstances[i]; }

References SubMeshInstances.

◆ GetSubMeshOrdered()

const StdSubMeshInstance& StdMeshInstance::GetSubMeshOrdered ( size_t  i) const
inline

Definition at line 591 of file StdMesh.h.

591 { return *SubMeshInstancesOrdered[i]; }

References SubMeshInstancesOrdered.

◆ GetVAOID()

unsigned int StdMeshInstance::GetVAOID ( ) const
inline

Definition at line 626 of file StdMesh.h.

626 { return vaoid ? vaoid : Mesh->GetVAOID(); }
unsigned int GetVAOID() const
Definition: StdMesh.h:214

References StdMesh::GetVAOID(), Mesh, and vaoid.

Here is the call graph for this function:

◆ InsertAnimationNode()

void StdMeshInstance::InsertAnimationNode ( AnimationNode node,
int  slot,
AnimationNode sibling,
ValueProvider weight,
bool  stop_previous_animation 
)
protected

Definition at line 1742 of file StdMesh.cpp.

1743 {
1744  assert(!sibling || !stop_previous_animation);
1745  // Default
1746  if (!sibling) sibling = GetRootAnimationForSlot(slot);
1747  assert(!sibling || sibling->Slot == slot);
1748 
1749  // Stop any animation already running in this slot?
1750  if (sibling && stop_previous_animation)
1751  {
1752  StopAnimation(sibling);
1753  sibling = nullptr;
1754  }
1755 
1756  // Find two subsequent numbers in case we need to create two nodes, so
1757  // script can deduce the second node.
1758  unsigned int Number1, Number2;
1759  for (Number1 = 0; Number1 < AnimationNodes.size(); ++Number1)
1760  if (AnimationNodes[Number1] == nullptr && (!sibling || Number1+1 == AnimationNodes.size() || AnimationNodes[Number1+1] == nullptr))
1761  break;
1762  /* for(Number2 = Number1+1; Number2 < AnimationNodes.size(); ++Number2)
1763  if(AnimationNodes[Number2] == nullptr)
1764  break;*/
1765  Number2 = Number1 + 1;
1766 
1767  weight->Value = Clamp(weight->Value, Fix0, itofix(1));
1768 
1769  if (Number1 == AnimationNodes.size()) AnimationNodes.push_back( (StdMeshInstance::AnimationNode*) nullptr);
1770  if (sibling && Number2 == AnimationNodes.size()) AnimationNodes.push_back( (StdMeshInstance::AnimationNode*) nullptr);
1771 
1772  AnimationNodes[Number1] = node;
1773  node->Number = Number1;
1774  node->Slot = slot;
1775 
1776  if (sibling)
1777  {
1778  AnimationNode* parent = new AnimationNode(node, sibling, weight);
1779  AnimationNodes[Number2] = parent;
1780  parent->Number = Number2;
1781  parent->Slot = slot;
1782 
1783  node->Parent = parent;
1784  parent->Parent = sibling->Parent;
1785  parent->LinearInterpolation.ChildLeft = sibling;
1786  parent->LinearInterpolation.ChildRight = node;
1787  if (sibling->Parent)
1788  {
1789  if (sibling->Parent->LinearInterpolation.ChildLeft == sibling)
1790  sibling->Parent->LinearInterpolation.ChildLeft = parent;
1791  else
1792  sibling->Parent->LinearInterpolation.ChildRight = parent;
1793  }
1794  else
1795  {
1796  // set new parent
1797  AnimationNodeList::iterator iter = GetStackIterForSlot(slot, false);
1798  // slot must not be empty, since sibling uses same slot
1799  assert(iter != AnimationStack.end() && *iter != nullptr);
1800  *iter = parent;
1801  }
1802 
1803  sibling->Parent = parent;
1804  }
1805  else
1806  {
1807  delete weight;
1808  AnimationNodeList::iterator iter = GetStackIterForSlot(slot, true);
1809  assert(!*iter); // we have a sibling if slot is not empty
1810  *iter = node;
1811  }
1812 
1813  SetBoneTransformsDirty(true);
1814 }
AnimationNode * GetRootAnimationForSlot(int slot)
Definition: StdMesh.cpp:1253

References AnimationNodes, AnimationStack, Clamp(), Fix0, GetRootAnimationForSlot(), GetStackIterForSlot(), itofix(), StdMeshInstanceAnimationNode::Number, StdMeshInstanceAnimationNode::Parent, SetBoneTransformsDirty(), StdMeshInstanceAnimationNode::Slot, StopAnimation(), and StdMeshInstanceValueProvider::Value.

Referenced by PlayAnimation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ PlayAnimation() [1/3]

StdMeshInstance::AnimationNode * StdMeshInstance::PlayAnimation ( const StdMeshAnimation animation,
int  slot,
AnimationNode sibling,
ValueProvider position,
ValueProvider weight,
bool  stop_previous_animation 
)

Definition at line 1175 of file StdMesh.cpp.

1176 {
1177  position->Value = Clamp(position->Value, Fix0, ftofix(animation.Length));
1178  AnimationNode* child = new AnimationNode(&animation, position);
1179  InsertAnimationNode(child, slot, sibling, weight, stop_previous_animation);
1180  return child;
1181 }
float Length
Definition: StdMesh.h:98
void InsertAnimationNode(AnimationNode *node, int slot, AnimationNode *sibling, ValueProvider *weight, bool stop_previous_animation)
Definition: StdMesh.cpp:1742

References Clamp(), Fix0, ftofix(), InsertAnimationNode(), StdMeshAnimation::Length, and StdMeshInstanceValueProvider::Value.

Here is the call graph for this function:

◆ PlayAnimation() [2/3]

StdMeshInstance::AnimationNode * StdMeshInstance::PlayAnimation ( const StdMeshBone bone,
const StdMeshTransformation trans,
int  slot,
AnimationNode sibling,
ValueProvider weight,
bool  stop_previous_animation 
)

Definition at line 1183 of file StdMesh.cpp.

1184 {
1185  AnimationNode* child = new AnimationNode(bone, trans);
1186  InsertAnimationNode(child, slot, sibling, weight, stop_previous_animation);
1187  return child;
1188 }

References InsertAnimationNode().

Here is the call graph for this function:

◆ PlayAnimation() [3/3]

StdMeshInstance::AnimationNode * StdMeshInstance::PlayAnimation ( const StdStrBuf animation_name,
int  slot,
AnimationNode sibling,
ValueProvider position,
ValueProvider weight,
bool  stop_previous_animation 
)

Definition at line 1167 of file StdMesh.cpp.

1168 {
1169  const StdMeshAnimation* animation = Mesh->GetSkeleton().GetAnimationByName(animation_name);
1170  if (!animation) { delete position; delete weight; return nullptr; }
1171 
1172  return PlayAnimation(*animation, slot, sibling, position, weight, stop_previous_animation);
1173 }
AnimationNode * PlayAnimation(const StdStrBuf &animation_name, int slot, AnimationNode *sibling, ValueProvider *position, ValueProvider *weight, bool stop_previous_animation)
Definition: StdMesh.cpp:1167
const StdMeshAnimation * GetAnimationByName(const StdStrBuf &name) const
Definition: StdMesh.cpp:398

References StdMeshSkeleton::GetAnimationByName(), StdMesh::GetSkeleton(), and Mesh.

Referenced by C4Object::SetAction(), and C4GraphicsOverlay::UpdateFacet().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReorderFaces()

void StdMeshInstance::ReorderFaces ( StdMeshMatrix global_trans)

Definition at line 1552 of file StdMesh.cpp.

1553 {
1554 #ifndef USE_CONSOLE
1555  for (auto & SubMeshInstance : SubMeshInstances)
1556  {
1557  StdSubMeshInstance& inst = *SubMeshInstance;
1558  assert((inst.Faces.size() > 0) && "StdMeshInstance sub-mesh instance has zero faces");
1559 
1560  if(inst.Faces.size() > 0 && inst.CurrentFaceOrdering != StdSubMeshInstance::FO_Fixed)
1561  {
1562  const StdMeshVertex* vertices;
1563  if(inst.GetSubMesh().GetNumVertices() > 0)
1564  vertices = &inst.GetSubMesh().GetVertices()[0];
1565  else
1566  vertices = &GetSharedVertices()[0];
1567  SortFacesArray(vertices, inst.Faces, inst.CurrentFaceOrdering, global_trans ? *global_trans : StdMeshMatrix::Identity());
1568  }
1569  }
1570 
1571  // TODO: Also reorder submeshes, attached meshes and include AttachTransformation for attached meshes...
1572 
1573  // Faces have been reordered: upload new order to GPU
1574  UpdateIBO();
1575 #endif
1576 }
void UpdateIBO()
Definition: StdMesh.cpp:1912
size_t GetNumVertices() const
Definition: StdMesh.h:165
const std::vector< Vertex > & GetVertices() const
Definition: StdMesh.h:163
std::vector< StdMeshFace > Faces
Definition: StdMesh.h:280
const StdSubMesh & GetSubMesh() const
Definition: StdMesh.h:265
FaceOrdering CurrentFaceOrdering
Definition: StdMesh.h:301

References StdSubMeshInstance::CurrentFaceOrdering, StdSubMeshInstance::Faces, StdSubMeshInstance::FO_Fixed, StdSubMesh::GetNumVertices(), GetSharedVertices(), StdSubMeshInstance::GetSubMesh(), StdSubMesh::GetVertices(), StdMeshMatrix::Identity(), SubMeshInstances, and UpdateIBO().

Referenced by C4Draw::RenderMesh().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ScanAttachTree()

template<typename IteratorType , typename FuncObj >
bool StdMeshInstance::ScanAttachTree ( IteratorType  begin,
IteratorType  end,
const FuncObj &  obj 
)
staticprotected

Definition at line 1702 of file StdMesh.cpp.

1703 {
1704  for (IteratorType iter = begin; iter != end; ++iter)
1705  {
1706  if (!obj(iter)) return false;
1707 
1708  // Scan attached tree of own children. For non-owned children,
1709  // we can't guarantee unique attach numbers.
1710  if( (*iter)->OwnChild)
1711  if (!ScanAttachTree((*iter)->Child->AttachChildren.begin(), (*iter)->Child->AttachChildren.end(), obj))
1712  return false;
1713  }
1714 
1715  return true;
1716 }

Referenced by AttachMesh(), DetachMesh(), and GetAttachedMeshByNumber().

Here is the caller graph for this function:

◆ SetAnimationBoneTransform()

void StdMeshInstance::SetAnimationBoneTransform ( AnimationNode node,
const StdMeshTransformation trans 
)

Definition at line 1271 of file StdMesh.cpp.

1272 {
1273  assert(node->GetType() == AnimationNode::CustomNode);
1274  *node->Custom.Transformation = trans;
1275  SetBoneTransformsDirty(true);
1276 }

References StdMeshInstanceAnimationNode::CustomNode, StdMeshInstanceAnimationNode::GetType(), and SetBoneTransformsDirty().

Here is the call graph for this function:

◆ SetAnimationPosition()

void StdMeshInstance::SetAnimationPosition ( AnimationNode node,
ValueProvider position 
)

Definition at line 1260 of file StdMesh.cpp.

1261 {
1262  assert(node->GetType() == AnimationNode::LeafNode);
1263  delete node->Leaf.Position;
1264  node->Leaf.Position = position;
1265 
1266  position->Value = Clamp(position->Value, Fix0, ftofix(node->Leaf.Animation->Length));
1267 
1268  SetBoneTransformsDirty(true);
1269 }

References Clamp(), Fix0, ftofix(), StdMeshInstanceAnimationNode::GetType(), StdMeshInstanceAnimationNode::LeafNode, SetBoneTransformsDirty(), and StdMeshInstanceValueProvider::Value.

Here is the call graph for this function:

◆ SetAnimationWeight()

void StdMeshInstance::SetAnimationWeight ( AnimationNode node,
ValueProvider weight 
)

Definition at line 1278 of file StdMesh.cpp.

1279 {
1280  assert(node->GetType() == AnimationNode::LinearInterpolationNode);
1281  delete node->LinearInterpolation.Weight; node->LinearInterpolation.Weight = weight;
1282 
1283  weight->Value = Clamp(weight->Value, Fix0, itofix(1));
1284 
1285  SetBoneTransformsDirty(true);
1286 }

References Clamp(), Fix0, StdMeshInstanceAnimationNode::GetType(), itofix(), StdMeshInstanceAnimationNode::LinearInterpolationNode, SetBoneTransformsDirty(), and StdMeshInstanceValueProvider::Value.

Here is the call graph for this function:

◆ SetBoneTransformsDirty()

void StdMeshInstance::SetBoneTransformsDirty ( bool  value)
protected

Definition at line 1893 of file StdMesh.cpp.

1894 {
1895  BoneTransformsDirty = value;
1896 
1897  // only if the value is true, so that updates happen
1898  if (value)
1899  {
1900  // Update attachment's attach transformations. Note this is done recursively.
1901  for (auto attach : AttachChildren)
1902  {
1903  if (attach->GetFlags() & AM_MatchSkeleton)
1904  {
1905  attach->Child->SetBoneTransformsDirty(value);
1906  }
1907  }
1908  }
1909 }

References AM_MatchSkeleton, AttachChildren, and BoneTransformsDirty.

Referenced by CompileFunc(), ExecuteAnimationNode(), InsertAnimationNode(), SetAnimationBoneTransform(), SetAnimationPosition(), SetAnimationWeight(), StopAnimation(), and UpdateBoneTransforms().

Here is the caller graph for this function:

◆ SetCompletion()

void StdMeshInstance::SetCompletion ( float  completion)

Definition at line 1152 of file StdMesh.cpp.

1153 {
1154  Completion = completion;
1155 
1156 #ifndef USE_CONSOLE
1157  // TODO: Load all submesh faces and then determine the ones to use from the
1158  // full pool.
1159  for(unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i)
1160  SubMeshInstances[i]->LoadFacesForCompletion(*this, Mesh->GetSubMesh(i), completion);
1161 
1162  // Faces have been reordered: upload new order to GPU
1163  UpdateIBO();
1164 #endif
1165 }

References Completion, StdMesh::GetNumSubMeshes(), StdMesh::GetSubMesh(), Mesh, SubMeshInstances, and UpdateIBO().

Referenced by C4Object::DoCon().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetFaceOrdering()

void StdMeshInstance::SetFaceOrdering ( FaceOrdering  ordering)

Definition at line 1118 of file StdMesh.cpp.

1119 {
1120 #ifndef USE_CONSOLE
1121  for (unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i)
1122  SubMeshInstances[i]->SetFaceOrdering(*this, Mesh->GetSubMesh(i), ordering);
1123 
1124  // Faces have been reordered: upload new order to GPU
1125  UpdateIBO();
1126 
1127  // Update attachments (only own meshes for now... others might be displayed both attached and non-attached...)
1128  // still not optimal.
1129  for (AttachedMeshIter iter = AttachChildren.begin(); iter != AttachChildren.end(); ++iter)
1130  if ((*iter)->OwnChild)
1131  (*iter)->Child->SetFaceOrdering(ordering);
1132 #endif
1133 }
AttachedMeshList::const_iterator AttachedMeshIter
Definition: StdMesh.h:544
void SetFaceOrdering(FaceOrdering ordering)
Definition: StdMesh.cpp:1118

References AttachChildren, StdMesh::GetNumSubMeshes(), StdMesh::GetSubMesh(), Mesh, SubMeshInstances, and UpdateIBO().

Referenced by C4EditCursor::DrawObject().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetFaceOrderingForClrModulation()

void StdMeshInstance::SetFaceOrderingForClrModulation ( uint32_t  clrmod)

Definition at line 1135 of file StdMesh.cpp.

1136 {
1137 #ifndef USE_CONSOLE
1138  for (unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i)
1140 
1141  // Faces have been reordered: upload new order to GPU
1142  UpdateIBO();
1143 
1144  // Update attachments (only own meshes for now... others might be displayed both attached and non-attached...)
1145  // still not optimal.
1146  for (AttachedMeshIter iter = AttachChildren.begin(); iter != AttachChildren.end(); ++iter)
1147  if ((*iter)->OwnChild)
1148  (*iter)->Child->SetFaceOrderingForClrModulation(clrmod);
1149 #endif
1150 }
void SetFaceOrderingForClrModulation(uint32_t clrmod)
Definition: StdMesh.cpp:1135

References AttachChildren, StdMesh::GetNumSubMeshes(), StdMesh::GetSubMesh(), Mesh, SubMeshInstances, and UpdateIBO().

Referenced by C4Object::CompileFunc(), C4GraphicsOverlay::Draw(), C4EditCursor::DrawObject(), C4GraphicsOverlay::DrawPicture(), C4Object::Init(), and C4Object::UpdateGraphics().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetMaterial()

void StdMeshInstance::SetMaterial ( size_t  i,
const StdMeshMaterial material 
)

Definition at line 1437 of file StdMesh.cpp.

1438 {
1439  assert(i < SubMeshInstances.size());
1440  SubMeshInstances[i]->SetMaterial(material);
1441 #ifndef USE_CONSOLE
1442  std::stable_sort(SubMeshInstancesOrdered.begin(), SubMeshInstancesOrdered.end(), StdMeshSubMeshInstanceVisibilityCmpPred());
1443 #endif
1444 }

References SubMeshInstances, and SubMeshInstancesOrdered.

◆ StopAnimation()

void StdMeshInstance::StopAnimation ( AnimationNode node)

Definition at line 1190 of file StdMesh.cpp.

1191 {
1192  ClearAnimationListRecursively(AnimationNodes, node);
1193 
1194  AnimationNode* parent = node->Parent;
1195  if (parent == nullptr)
1196  {
1197  AnimationNodeList::iterator iter = GetStackIterForSlot(node->Slot, false);
1198  assert(iter != AnimationStack.end() && *iter == node);
1199  AnimationStack.erase(iter);
1200  delete node;
1201  }
1202  else
1203  {
1204  assert(parent->Type == AnimationNode::LinearInterpolationNode);
1205 
1206  // Remove parent interpolation node and re-link
1207  AnimationNode* other_child;
1208  if (parent->LinearInterpolation.ChildLeft == node)
1209  {
1210  other_child = parent->LinearInterpolation.ChildRight;
1211  parent->LinearInterpolation.ChildRight = nullptr;
1212  }
1213  else
1214  {
1215  other_child = parent->LinearInterpolation.ChildLeft;
1216  parent->LinearInterpolation.ChildLeft = nullptr;
1217  }
1218 
1219  if (parent->Parent)
1220  {
1221  assert(parent->Parent->Type == AnimationNode::LinearInterpolationNode);
1222  if (parent->Parent->LinearInterpolation.ChildLeft == parent)
1223  parent->Parent->LinearInterpolation.ChildLeft = other_child;
1224  else
1225  parent->Parent->LinearInterpolation.ChildRight = other_child;
1226  other_child->Parent = parent->Parent;
1227  }
1228  else
1229  {
1230  AnimationNodeList::iterator iter = GetStackIterForSlot(node->Slot, false);
1231  assert(iter != AnimationStack.end() && *iter == parent);
1232  *iter = other_child;
1233 
1234  other_child->Parent = nullptr;
1235  }
1236 
1237  AnimationNodes[parent->Number] = nullptr;
1238  // Recursively deletes parent and its descendants
1239  delete parent;
1240  }
1241 
1242  while (!AnimationNodes.empty() && AnimationNodes.back() == nullptr)
1243  AnimationNodes.erase(AnimationNodes.end()-1);
1244  SetBoneTransformsDirty(true);
1245 }
AnimationNode * Parent
Definition: StdMesh.h:367

References AnimationNodes, AnimationStack, GetStackIterForSlot(), StdMeshInstanceAnimationNode::LinearInterpolationNode, StdMeshInstanceAnimationNode::Number, StdMeshInstanceAnimationNode::Parent, SetBoneTransformsDirty(), StdMeshInstanceAnimationNode::Slot, and StdMeshInstanceAnimationNode::Type.

Referenced by ExecuteAnimation(), ExecuteAnimationNode(), InsertAnimationNode(), C4Object::SetAction(), StdMeshAnimationUpdate::Update(), StdMeshUpdate::Update(), and ~StdMeshInstance().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateBoneTransforms()

bool StdMeshInstance::UpdateBoneTransforms ( )

Definition at line 1471 of file StdMesh.cpp.

1472 {
1473  bool was_dirty = BoneTransformsDirty;
1474 
1475  // Nothing changed since last time
1476  if (BoneTransformsDirty)
1477  {
1478  // Compute transformation matrix for each bone.
1479  for (unsigned int i = 0; i < BoneTransforms.size(); ++i)
1480  {
1481  StdMeshTransformation Transformation;
1482 
1483  const StdMeshBone& bone = Mesh->GetSkeleton().GetBone(i);
1484  const StdMeshBone* parent = bone.GetParent();
1485  assert(!parent || parent->Index < i);
1486 
1487  bool have_transform = false;
1488  for (auto & j : AnimationStack)
1489  {
1490  if (have_transform)
1491  {
1492  StdMeshTransformation other;
1493  if (j->GetBoneTransform(i, other))
1494  Transformation = StdMeshTransformation::Nlerp(Transformation, other, 1.0f); // TODO: Allow custom weighing for slot combination
1495  }
1496  else
1497  {
1498  have_transform = j->GetBoneTransform(i, Transformation);
1499  }
1500  }
1501 
1502  if (!have_transform)
1503  {
1504  if (parent)
1505  BoneTransforms[i] = BoneTransforms[parent->Index];
1506  else
1508  }
1509  else
1510  {
1512  if (parent) BoneTransforms[i] = BoneTransforms[parent->Index] * BoneTransforms[i];
1513  }
1514  }
1515  }
1516 
1517  // Update attachment's attach transformations. Note this is done recursively.
1518  for (auto attach : AttachChildren)
1519  {
1520  const bool ChildBoneTransformsDirty = attach->Child->BoneTransformsDirty;
1521  attach->Child->UpdateBoneTransforms();
1522 
1523  if (BoneTransformsDirty || ChildBoneTransformsDirty || attach->FinalTransformDirty)
1524  {
1525  was_dirty = true;
1526 
1527  // Compute matrix to change the coordinate system to the one of the attached bone:
1528  // The idea is that a vertex at the child bone's position transforms to the parent bone's position.
1529  // Therefore (read from right to left) we first apply the inverse of the child bone transformation,
1530  // then an optional scaling matrix, and finally the parent bone transformation
1531 
1532  // TODO: we can cache the three matrices in the middle since they don't change over time,
1533  // reducing this to two matrix multiplications instead of four each frame.
1534  // Might even be worth to compute the complete transformation directly when rendering then
1535  // (saves per-instance memory, but requires recomputation if the animation does not change).
1536  // TODO: We might also be able to cache child inverse, and only recomupte it if
1537  // child bone transforms are dirty (saves matrix inversion for unanimated attach children).
1538  attach->FinalTrans = GetBoneTransform(attach->ParentBone)
1540  * attach->AttachTrans
1541  * StdMeshMatrix::Transform(attach->Child->Mesh->GetSkeleton().GetBone(attach->ChildBone).InverseTransformation)
1542  * StdMeshMatrix::Inverse(attach->Child->GetBoneTransform(attach->ChildBone));
1543 
1544  attach->FinalTransformDirty = false;
1545  }
1546  }
1547 
1548  SetBoneTransformsDirty(false);
1549  return was_dirty;
1550 }
StdMeshTransformation InverseTransformation
Definition: StdMesh.h:39
StdMeshTransformation Transformation
Definition: StdMesh.h:37
const StdMeshBone * GetParent() const
Definition: StdMesh.h:41
const StdMeshMatrix & GetBoneTransform(size_t i) const
Definition: StdMesh.cpp:1446
static StdMeshMatrix Inverse(const StdMeshMatrix &mat)
static StdMeshMatrix Transform(const StdMeshTransformation &transform)
const StdMeshBone & GetBone(size_t i) const
Definition: StdMesh.h:116
static StdMeshTransformation Nlerp(const StdMeshTransformation &lhs, const StdMeshTransformation &rhs, float w)

References AnimationStack, AttachChildren, BoneTransforms, BoneTransformsDirty, StdMeshSkeleton::GetBone(), GetBoneTransform(), StdMeshBone::GetParent(), StdMesh::GetSkeleton(), StdMeshMatrix::Identity(), StdMeshBone::Index, StdMeshMatrix::Inverse(), StdMeshBone::InverseTransformation, Mesh, StdMeshTransformation::Nlerp(), SetBoneTransformsDirty(), StdMeshMatrix::Transform(), and StdMeshBone::Transformation.

Referenced by C4Draw::RenderMesh().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateIBO()

void StdMeshInstance::UpdateIBO ( )
protected

Definition at line 1912 of file StdMesh.cpp.

1913 {
1914  // First, find out whether we have fixed face ordering or not
1915  bool all_submeshes_fixed = true;
1916  for (StdSubMeshInstance* inst : SubMeshInstances)
1917  {
1918  all_submeshes_fixed = (inst->GetFaceOrdering() == StdSubMeshInstance::FO_Fixed);
1919  if (!all_submeshes_fixed) break;
1920 
1921  // If true, submesh is 100% complete
1922  all_submeshes_fixed = inst->GetNumFaces() == inst->GetSubMesh().GetNumFaces();
1923  if (!all_submeshes_fixed) break;
1924  }
1925 
1926  // If the face ordering is fixed, then we don't need a custom
1927  // IBO. This is typically the case for all meshes without transparency
1928  // and 100% completion.
1929  if (all_submeshes_fixed)
1930  {
1931  if (ibo) glDeleteBuffers(1, &ibo);
1932  if (vaoid) pGL->FreeVAOID(vaoid);
1933  ibo = 0; vaoid = 0;
1934  }
1935  else
1936  {
1937  // We have a custom face ordering, or we render only a subset
1938  // of our faces. Create a custom IBO and upload the index
1939  // data.
1940  if (ibo == 0)
1941  {
1942  // This is required, because the IBO binding is part
1943  // of the VAO state. If we create a new IBO we cannot
1944  // keep using any old VAO. But we always create and
1945  // destroy them together, so we can assert here.
1946  assert(vaoid == 0);
1947 
1948  size_t total_faces = 0;
1949  for (unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i)
1950  total_faces += Mesh->GetSubMesh(i).GetNumFaces();
1951 
1952  glGenBuffers(1, &ibo);
1953  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
1954 
1955  // TODO: Optimize mode. In many cases this is still fairly static.
1956  glBufferData(GL_ELEMENT_ARRAY_BUFFER, total_faces * 3 * sizeof(GLuint), nullptr, GL_STREAM_DRAW);
1957  }
1958  else
1959  {
1960  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
1961  }
1962 
1963  for (StdSubMeshInstance* inst : SubMeshInstances)
1964  {
1965  assert(inst->GetNumFaces() <= inst->GetSubMesh().GetNumFaces());
1966  glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, inst->GetSubMesh().GetOffsetInIBO(), inst->GetNumFaces() * 3 * sizeof(GLuint), &inst->Faces[0]);
1967  }
1968 
1969  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1970 
1971  if (vaoid == 0)
1972  vaoid = pGL->GenVAOID();
1973  }
1974 }
unsigned int GenVAOID()
Definition: C4DrawGL.cpp:927
size_t GetNumFaces() const
Definition: StdMesh.h:168

References StdSubMeshInstance::FO_Fixed, CStdGL::FreeVAOID(), CStdGL::GenVAOID(), StdSubMesh::GetNumFaces(), StdMesh::GetNumSubMeshes(), StdMesh::GetSubMesh(), ibo, Mesh, pGL, SubMeshInstances, and vaoid.

Referenced by ReorderFaces(), SetCompletion(), SetFaceOrdering(), and SetFaceOrderingForClrModulation().

Here is the call graph for this function:
Here is the caller graph for this function:

Friends And Related Function Documentation

◆ StdMeshAnimationUpdate

friend class StdMeshAnimationUpdate
friend

Definition at line 396 of file StdMesh.h.

◆ StdMeshMaterialUpdate

friend class StdMeshMaterialUpdate
friend

Definition at line 395 of file StdMesh.h.

◆ StdMeshUpdate

friend class StdMeshUpdate
friend

Definition at line 397 of file StdMesh.h.

Member Data Documentation

◆ AnimationNodes

AnimationNodeList StdMeshInstance::AnimationNodes
protected

◆ AnimationStack

◆ AttachChildren

◆ AttachParent

AttachedMesh* StdMeshInstance::AttachParent
protected

◆ BoneTransforms

std::vector<StdMeshMatrix> StdMeshInstance::BoneTransforms
protected

◆ BoneTransformsDirty

bool StdMeshInstance::BoneTransformsDirty
protected

Definition at line 663 of file StdMesh.h.

Referenced by SetBoneTransformsDirty(), StdMeshUpdate::Update(), and UpdateBoneTransforms().

◆ Completion

float StdMeshInstance::Completion
protected

Definition at line 649 of file StdMesh.h.

Referenced by GetCompletion(), and SetCompletion().

◆ ibo

GLuint StdMeshInstance::ibo
protected

Definition at line 670 of file StdMesh.h.

Referenced by GetIBO(), UpdateIBO(), and ~StdMeshInstance().

◆ Mesh

◆ SubMeshInstances

◆ SubMeshInstancesOrdered

std::vector<StdSubMeshInstance*> StdMeshInstance::SubMeshInstancesOrdered
protected

◆ vaoid

unsigned int StdMeshInstance::vaoid
protected

Definition at line 671 of file StdMesh.h.

Referenced by GetVAOID(), UpdateIBO(), and ~StdMeshInstance().


The documentation for this class was generated from the following files: