From d5897854bef8435b9f6232870985355d18961b92 Mon Sep 17 00:00:00 2001 From: leper Date: Thu, 11 Jul 2013 22:53:31 +0000 Subject: [PATCH] Allow terrain aligned props. Patch by sanderd17. Fixes #2033. This was SVN commit r13549. --- .../actors/structures/persians/stables.xml | 6 +-- source/graphics/Model.cpp | 44 ++++++++++++++----- source/graphics/Model.h | 14 ++++-- source/graphics/ObjectBase.cpp | 8 +++- source/graphics/ObjectBase.h | 5 ++- source/graphics/ObjectEntry.cpp | 11 ++--- source/graphics/ObjectEntry.h | 7 ++- source/graphics/ObjectManager.cpp | 4 +- 8 files changed, 72 insertions(+), 27 deletions(-) diff --git a/binaries/data/mods/public/art/actors/structures/persians/stables.xml b/binaries/data/mods/public/art/actors/structures/persians/stables.xml index a2085d6fe5..8bfeebe436 100644 --- a/binaries/data/mods/public/art/actors/structures/persians/stables.xml +++ b/binaries/data/mods/public/art/actors/structures/persians/stables.xml @@ -7,9 +7,9 @@ - - - + + + diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index 95738b18a8..3381d2c44e 100644 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2013 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -36,13 +36,15 @@ #include "ps/Profile.h" #include "ps/CLogger.h" #include "renderer/Renderer.h" +#include "simulation2/Simulation2.h" +#include "simulation2/components/ICmpTerrain.h" + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // Constructor -CModel::CModel(CSkeletonAnimManager& skeletonAnimManager) - : m_Flags(0), m_Anim(NULL), m_AnimTime(0), - m_BoneMatrices(NULL), - m_AmmoPropPoint(NULL), m_AmmoLoadedProp(0), +CModel::CModel(CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation) + : m_Flags(0), m_Anim(NULL), m_AnimTime(0), m_Simulation(simulation), + m_BoneMatrices(NULL), m_AmmoPropPoint(NULL), m_AmmoLoadedProp(0), m_SkeletonAnimManager(skeletonAnimManager) { } @@ -380,7 +382,8 @@ void CModel::ValidatePosition() { const Prop& prop=m_Props[j]; - CMatrix3D proptransform = prop.m_Point->m_Transform;; + CMatrix3D proptransform = prop.m_Point->m_Transform; + if (prop.m_Point->m_BoneIndex != 0xff) { CMatrix3D boneMatrix = m_BoneMatrices[prop.m_Point->m_BoneIndex]; @@ -393,7 +396,26 @@ void CModel::ValidatePosition() // not relative to any bone; just apply world-space transformation (i.e. relative to object-space origin) proptransform.Concatenate(m_Transform); } - + + // Adjust prop height to terrain level when needed + if (prop.m_maxHeight != 0.f || prop.m_minHeight != 0.f) + { + CVector3D propTranslation = proptransform.GetTranslation(); + CVector3D objTranslation = m_Transform.GetTranslation(); + + CmpPtr cmpTerrain(m_Simulation, SYSTEM_ENTITY); + if (cmpTerrain) + { + float objTerrain = cmpTerrain->GetExactGroundLevel(objTranslation.X, objTranslation.Z); + float propTerrain = cmpTerrain->GetExactGroundLevel(propTranslation.X, propTranslation.Z); + float translateHeight = std::min(prop.m_maxHeigth, + std::max(prop.m_minHeight, propTerrain - objTerrain)); + CMatrix3D translate = CMatrix3D(); + translate.SetTranslation(0.f, translateHeight, 0.f); + proptransform.Concatenate(translate); + } + } + prop.m_Model->SetTransform(proptransform); prop.m_Model->ValidatePosition(); } @@ -484,7 +506,7 @@ void CModel::CopyAnimationFrom(CModel* source) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // AddProp: add a prop to the model on the given point -void CModel::AddProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry) +void CModel::AddProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry, float minHeight, float maxHeight) { // position model according to prop point position @@ -496,6 +518,8 @@ void CModel::AddProp(const SPropPoint* point, CModelAbstract* model, CObjectEntr prop.m_Point = point; prop.m_Model = model; prop.m_ObjectEntry = objectentry; + prop.m_minHeight = minHeight; + prop.m_maxHeight = maxHeight; m_Props.push_back(prop); } @@ -564,7 +588,7 @@ CModelAbstract* CModel::FindFirstAmmoProp() // Clone: return a clone of this model CModelAbstract* CModel::Clone() const { - CModel* clone = new CModel(m_SkeletonAnimManager); + CModel* clone = new CModel(m_SkeletonAnimManager, m_Simulation); clone->m_ObjectBounds = m_ObjectBounds; clone->InitModel(m_pModelDef); clone->SetMaterial(m_Material); @@ -577,7 +601,7 @@ CModelAbstract* CModel::Clone() const if (m_AmmoPropPoint && i == m_AmmoLoadedProp) clone->AddAmmoProp(m_Props[i].m_Point, m_Props[i].m_Model->Clone(), m_Props[i].m_ObjectEntry); else - clone->AddProp(m_Props[i].m_Point, m_Props[i].m_Model->Clone(), m_Props[i].m_ObjectEntry); + clone->AddProp(m_Props[i].m_Point, m_Props[i].m_Model->Clone(), m_Props[i].m_ObjectEntry, m_Props[i].m_minHeight, m_Props[i].m_maxHeight); } return clone; diff --git a/source/graphics/Model.h b/source/graphics/Model.h index 6de1fca8f1..8b2b4a2f7f 100644 --- a/source/graphics/Model.h +++ b/source/graphics/Model.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Wildfire Games. +/* Copyright (C) 2013 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -35,6 +35,7 @@ class CObjectEntry; class CSkeletonAnim; class CSkeletonAnimDef; class CSkeletonAnimManager; +class CSimulation2; #define MODELFLAG_CASTSHADOWS (1<<0) #define MODELFLAG_NOLOOPANIMATION (1<<1) @@ -55,6 +56,9 @@ public: { Prop() : m_Point(0), m_Model(0), m_ObjectEntry(0), m_Hidden(false) {} + float m_minHeight; + float m_maxHeight; + /** * Location of the prop point within its parent model, relative to either a bone in the parent model or to the * parent model's origin. See the documentation for @ref SPropPoint for more details. @@ -75,10 +79,11 @@ public: public: // constructor - CModel(CSkeletonAnimManager& skeletonAnimManager); + CModel(CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation); // destructor ~CModel(); + /// Dynamic cast virtual CModel* ToCModel() { @@ -205,7 +210,7 @@ public: /** * Add a prop to the model on the given point. */ - void AddProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry); + void AddProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry, float minHeight = 0.f, float maxHeight = 0.f); /** * Add a prop to the model on the given point, and treat it as the ammo prop. @@ -250,6 +255,9 @@ public: private: // delete anything allocated by the model void ReleaseData(); + + // Needed for terrain aligned props + CSimulation2& m_Simulation; // object flags int m_Flags; diff --git a/source/graphics/ObjectBase.cpp b/source/graphics/ObjectBase.cpp index 3cb2aae37f..becda45bad 100644 --- a/source/graphics/ObjectBase.cpp +++ b/source/graphics/ObjectBase.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2013 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -80,6 +80,8 @@ bool CObjectBase::Load(const VfsPath& pathname) AT(angle); AT(offsetx); AT(offsetz); + AT(minheight); + AT(maxheight); #undef AT #undef EL @@ -246,6 +248,10 @@ bool CObjectBase::Load(const VfsPath& pathname) prop.m_PropPointName = pe.Value; else if (pe.Name == at_actor) prop.m_ModelName = pe.Value.FromUTF8(); + else if (pe.Name == at_minheight) + prop.m_minHeight = pe.Value.ToFloat(); + else if (pe.Name == at_maxheight) + prop.m_maxHeight = pe.Value.ToFloat(); } currentVariant->m_Props.push_back(prop); } diff --git a/source/graphics/ObjectBase.h b/source/graphics/ObjectBase.h index 708551526e..a12918a6ca 100644 --- a/source/graphics/ObjectBase.h +++ b/source/graphics/ObjectBase.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2013 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -59,6 +59,9 @@ public: CStr m_PropPointName; // name of the model file - art/actors/props/sword.xml or whatever CStrW m_ModelName; + // allow the prop to ajust the height from minHeight to maxHeight relative to the main model + float m_minHeight; + float m_maxHeight; }; struct Samp diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index ac36f73d7e..59c44ccdf0 100644 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Wildfire Games. +/* Copyright (C) 2013 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -35,11 +35,12 @@ #include "ps/Game.h" #include "ps/World.h" #include "renderer/Renderer.h" +#include "simulation2/Simulation2.h" #include -CObjectEntry::CObjectEntry(CObjectBase* base) : - m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f), m_Model(NULL), m_Outdated(false) +CObjectEntry::CObjectEntry(CObjectBase* base, CSimulation2& simulation) : + m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f), m_Model(NULL), m_Outdated(false), m_Simulation(simulation) { } @@ -123,7 +124,7 @@ bool CObjectEntry::BuildVariation(const std::vector >& selections } // delete old model, create new - CModel* model = new CModel(objectManager.GetSkeletonAnimManager()); + CModel* model = new CModel(objectManager.GetSkeletonAnimManager(), m_Simulation); delete m_Model; m_Model = model; model->SetMaterial(g_Renderer.GetMaterialManager().LoadMaterial(m_Base->m_Material)); @@ -234,7 +235,7 @@ bool CObjectEntry::BuildVariation(const std::vector >& selections if (isAmmo) model->AddAmmoProp(proppoint, propmodel, oe); else - model->AddProp(proppoint, propmodel, oe); + model->AddProp(proppoint, propmodel, oe, prop.m_minHeight, prop.m_maxHeight); if (propmodel->ToCModel()) propmodel->ToCModel()->SetAnimation(oe->GetRandomAnimation("idle")); } diff --git a/source/graphics/ObjectEntry.h b/source/graphics/ObjectEntry.h index f0610d4ad8..132ceb917e 100644 --- a/source/graphics/ObjectEntry.h +++ b/source/graphics/ObjectEntry.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Wildfire Games. +/* Copyright (C) 2013 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,6 +22,7 @@ class CModelAbstract; class CSkeletonAnim; class CObjectBase; class CObjectManager; +class CSimulation2; struct SPropPoint; #include @@ -37,7 +38,7 @@ struct SPropPoint; class CObjectEntry { public: - CObjectEntry(CObjectBase* base); + CObjectEntry(CObjectBase* base, CSimulation2& simulation); ~CObjectEntry(); // Construct this actor, using the specified variation selections @@ -75,6 +76,8 @@ public: bool m_Outdated; private: + CSimulation2& m_Simulation; + typedef std::multimap SkeletonAnimMap; SkeletonAnimMap m_Animations; // TODO: something more memory-efficient than storing loads of similar strings for each unit? diff --git a/source/graphics/ObjectManager.cpp b/source/graphics/ObjectManager.cpp index e1117721fe..b8bd6b8b41 100644 --- a/source/graphics/ObjectManager.cpp +++ b/source/graphics/ObjectManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2013 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -139,7 +139,7 @@ CObjectEntry* CObjectManager::FindObjectVariation(CObjectBase* base, const std:: // makes more sense (e.g. use shared_ptr); for now I'll just leak, to avoid making the logic // more complex than it is already is, since this only matters for the rare case of hotloading. - CObjectEntry* obj = new CObjectEntry(base); // TODO: type ? + CObjectEntry* obj = new CObjectEntry(base, m_Simulation); // TODO: type ? // TODO (for some efficiency): use the pre-calculated choices for this object, // which has already worked out what to do for props, instead of passing the